home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / archiver / lzhsourc.lzh / LZH.SRC / LHARC.C < prev    next >
C/C++ Source or Header  |  1992-07-02  |  100KB  |  2,791 lines

  1. /*{{{  defines*/
  2.  
  3. /*************************************************
  4.                 LHarc version 1.13b (c)Yoshi, 1988-89.
  5.                 main module : 1989/ 5/14
  6.  
  7.                 adaption to ATARI ST with TURBO-C 1.1
  8.                 and some corrections
  9.                 by J. Moeller 1990/01/31
  10.  
  11.                 Assembly and more corrections with
  12.                 Turbo-C 1.0, 2.0, by Thomas Quester
  13.  
  14. HTAB = 4
  15. *************************************************/
  16.  
  17. #define ThisSystem 'A'  /* Atari */
  18.  
  19. #include <stdio.h>
  20. #include <ctype.h>
  21. #include <string.h>
  22. #include <process.h>
  23. #include <stdlib.h>
  24. #include <setjmp.h>
  25. #include <errno.h>
  26. #include <tos.h>
  27.  
  28. #ifdef Japanese
  29. #include        "usage_j.h"
  30. #else
  31. #ifdef German
  32. #include        "usage_d.h"
  33. #else
  34. #include        "usage_e.h"
  35. #endif
  36. #endif
  37. #define from extern
  38. #ifndef __TOS__
  39. #include <alloc.h>
  40. #include <fcntl.h>
  41. #include <io.h>
  42. #include <dir.h>
  43. #include <dos.h>
  44. #else
  45. #include <ext.h>
  46. #include <tos.h>
  47. #define MAXPATH 119
  48. #define MAXDIR  102
  49. #define MAXNUMFILES 128
  50. #define far
  51. #define huge
  52. #define setmode(stream,mode)    /* sorry: no such function known */
  53. #include "goodputc.h"
  54. #endif
  55.  
  56. #define UNKNOWNERR      0
  57. #define INVCMDERR       1
  58. #define MANYPATERR      2
  59. #define NOARCNMERR      3
  60. #define NOFNERR         4
  61. #define NOARCERR        5
  62. #define RENAMEERR       6
  63. #define MKTMPERR        7
  64. #define DUPFNERR        8
  65. #define TOOMANYERR      9
  66. #define TOOLONGERR      10
  67. #define NOFILEERR       11
  68. #define MKFILEERR       12
  69. #define RDERR           13
  70. #define WTERR           14
  71. #define MEMOVRERR       15
  72. #define INVSWERR        16
  73. #define CTRLBRK         17
  74. #define NOMATCHERR      18
  75. #define COPYERR         19
  76. #define NOTLZH          20
  77. #define OVERWT          21
  78. #define MKDIR           22
  79. #define MKDIRERR        23
  80. #define CRCERR          24
  81. #define RDONLY          25
  82.  
  83.  
  84. #ifndef __TOS__
  85. #define PAGER           "less"
  86. #define BUFFERSIZ       4096L
  87. #else
  88. #define PAGER           "less.ttp"
  89. #define BUFFERSIZ       16384L
  90. #endif
  91. #define MAXBLK          64
  92. #define MAX_PAT         512
  93. #define FAULT           0
  94. #define SUCCS           ~FAULT
  95.  
  96. #ifndef __TOS__
  97. #define getch() (bdos(0x08, 0, 0) & 0xff)
  98. #endif
  99. #define min(a,b)        ((a>b) ? b : a)
  100. typedef unsigned char uchar;
  101. typedef unsigned int uint;
  102. typedef unsigned long ulong;
  103.  
  104. FILE  *file1, *file2, *file3;
  105. from FILE *infile;
  106. from FILE *outfile;
  107. from int FileFits;                      /* 1, wenn File passt */
  108. int   cmd;                              /* command */
  109. int   cmdupdate;                        /* Not zero, when updating archive */
  110. int   errorlevel = 0;                   /* return value */
  111. jmp_buf exit_jmp;                       /* Jump to exit of program */
  112. extern long  textsize;                  /* file size before compression */
  113. extern long  codesize;                  /* file size after      compression */
  114. from long  blocksize;                   /* Bytes bis "*" (norm. 4096) */
  115. long  arcpos0;                          /* position pointer for archive */
  116. uchar *basedir;                         /* base directory (home-directory) */
  117. uchar *wdir = "";                       /* work directory */
  118. uchar workdir[MAXPATH];                 /* work directory */
  119. uchar *infname;                         /* input  file name (for error message) */
  120. uchar *outfname;                        /* output file name (for error message)*/
  121. int   attr;                             /* file attributes for search files */
  122. int   Nfile;                            /* number of files which was found */
  123. /* >> fbmax is used to compute the total amout used by filenames << */
  124. ulong fblft, fbsize;
  125. ulong fbmax,fbfiles;                    /* for buffers handling file names */
  126. #ifndef __TOS__
  127. uint  seg;                              /* beginning segment of file name buffers */
  128. #endif
  129. uchar far *fbuf, huge *fbnxt;           /* pointer to file name buffers */
  130. uchar arcname[MAXPATH];                 /* archive name */
  131. uchar pathname[MAXPATH];                /* work for file name (extracting) */
  132. uchar dospathname[MAXPATH];             /* work for filename (8+3 chars)   */
  133. uchar filename[MAXPATH];                /* work for file name (for file in archive) */
  134. uchar comment[MAXPATH];                 /* Komments in archives */
  135. uchar SystemId;                         /* Archiv createt on system */
  136. uchar freezing=0;                       /* Enables extended headers */
  137. uchar UseExthdr=0;                      /* 1, if gethdr has to use exthdrs */
  138. int   patno;                            /* No. of path names in command line */
  139. int   UnixFile;                            /* !=0 if filename is not 8+3        */
  140. uchar patfile[MAX_PAT][12];     /* file name in command line */
  141. uchar *patpath[MAX_PAT];                /* directory name in command line */
  142. int   patcnt[MAX_PAT];                  /* counts which this name matched */
  143. uchar patnul[] = "*.*";                 /* default path name */
  144. uchar backup1[MAXPATH], backup2[MAXPATH];            /* temporary file names */
  145. char *TheInputBuf;                               /* Input-Buffer */
  146. char *TheOutputBuf;
  147. from int unpackable;
  148.            /* temporary file names */
  149. uchar flg_r = 0, flg_p = 0, flg_x = 0, flg_m = 0;
  150. uchar flg_a = 0, flg_c = 0, flg_v = 0, flg_w = 0;
  151. uchar flg_d = 0, flg_u = 0, flg_s = 0, flg_k = 0;
  152. uchar flg_e = 0;
  153. uchar flg_unpacked; /* Set to 1, if 100% used in pack_afx */
  154. uchar elen=3;
  155.  
  156. from uchar flg_n = 0;
  157. uchar flg_t = 0;
  158. uchar flg_5 = 0;
  159. uchar flg_arc = 0,flg_backup=0;
  160. uchar method=5, FlgMethod=5;
  161. #ifdef __TOS__
  162. uchar   flg_h = 0;
  163. #endif
  164.                                            /* switches */
  165. uchar copying = 0;                         /* turn on when copying temporary file */
  166. uchar crcflg = 0;                         /* force copyfile() to calculate CRC*/
  167. uchar tstflg = 0;                         /* turn on in 't' command */
  168. uchar swchar;                          /* switch character */
  169. uchar *pager = PAGER;                  /* utility used in 'p /v' mode */
  170. from uint  crc;                          /* calculated CRC code */
  171. uchar *keyword = "";                         /* key word for auto-execution */
  172.  
  173. struct filebuf {                         /* work for file name buffer */
  174.         void far *next;
  175.         uchar fpos;                          /* position of file name */
  176.         uchar cpos;                          /* position of effective path name */
  177.         uchar dir[MAXDIR];                 /* full path name */
  178. } fb0, fb1;
  179.  
  180. extern char  *errmes[];                 /* array of pointers to error messages */
  181. /* extern uchar  use[]; */                       /* usage */
  182. extern uchar buf2[], buf3[];            /* I/O buffers */
  183.  
  184. #ifdef Japanese
  185. /* routines for handling Japanese strings (import from util.c) */
  186. extern uchar *j_strupr(uchar *p);
  187. extern int        j_strcmp(char *p, char *q);
  188. extern uchar *j_strchr(char *p, uint c);
  189. extern uchar *j_strrchr(char *p, uint c);
  190. extern void   slash2yen(uchar *p);                      /* convert '/' to '\' */
  191. extern void   yen2shlas(uchar *p);
  192.  
  193. #define strupr j_strupr
  194. #define strcmp j_strcmp
  195. #define strchr j_strchr
  196. #define strrchr j_strrchr
  197. #else
  198. extern void   slash2yen(uchar *p);                      /* convert '/' to '\' */
  199. extern void   yen2slash(uchar *p);
  200.  
  201. /* #define slash2yen(p) */ /*
  202. extern void slash2yen(uchar *p);                        /* convert '/' to '\' */
  203.  
  204. #endif
  205.  
  206. extern int        getfattr(uchar *fn);                  /* get file attributes */
  207. extern void   setfattr(uchar *fn, int attr);/* set file attributes */
  208. #ifndef __TOS__
  209. extern uchar  getswchar(void);                          /* get switch character */
  210. extern int test_afx(char *s);           /* Überprüft, ob Datei gepackt ist */
  211. #else
  212. extern char *stpcpy (char *dest, char *source);
  213. extern int mkdir (char *path);
  214. #define getswchar() ('/')
  215. #endif
  216.  
  217. #ifdef __TOS__
  218.   struct outbuf
  219.   {
  220.     char *ptr;          /* aktuelles Zeichen */
  221.     char *last;         /* letztes Zeichen   */
  222.     char *base;         /* erstes Zeichen    */
  223.     FILE *file;         /* dateiname             */
  224.   } OutBufMem;
  225. struct outbuf *OutBuf;
  226.  
  227. #endif __TOS__
  228.  
  229. extern void mkcrc (void);                                       /* import from 'LZS.*' */
  230. extern void copyfile (FILE *Source, FILE *Dest, long size);
  231. extern void Encode (void);                                      /* import from 'LZHUF.*' */
  232. extern ulong encode5(ulong orgsize);
  233. extern void init_encode5(void);
  234. extern void EncodeOld(void);
  235. extern void Decode (void);
  236. extern void decode_lh5(ulong orgsize,ulong pacsize);
  237. extern  void DecodeOld(void);
  238.  
  239. extern char M_NOMATCHERR[];
  240. extern char M_COPYERR[];
  241. extern char M_NOTLZH[];
  242. extern char M_OVERWT[];
  243. extern char M_MKDIR[];
  244. extern char M_MKDIRERR[];
  245. extern char M_CRCERR[];
  246. extern char M_RDONLY[];
  247.  
  248. struct ftime arcstamp /* = {0L} */;     /* time stamp for archive */
  249.  
  250. struct LzHead {                                 /* file header */
  251.         uchar HeadSiz, HeadChk, HeadID[5];
  252.         ulong PacSiz, OrgSiz;           /* 16- and 32-bit Intel format !!!*/
  253.         struct ftime Ftime;
  254.         uint  Attr;
  255.         uchar Fname[MAXPATH];           /* packed filename + crc */
  256. } Hdr1, Hdr2;
  257.  
  258. #ifndef __TOS__
  259. struct exeHead {                                /* EXE header for SFX */
  260.         uint exeID, byte, page, reloc;
  261.         uint hdrsize, minalloc, maxalloc, initSS;
  262.         uint initSP, chksum, initIP, initCS;
  263.         uint reloctab, overlay, dummy1, dummy2;
  264. } ExeHdr = {
  265.         'MZ', 0, 0, 0, 2, 0, 0xffff, 0xfff0,
  266.         0x100, 0, 0x100, 0xfff0, 0x1e, 0, 0, 0
  267. };
  268. #endif
  269.  
  270. #define FTimeToUIntTime(t) ((((t.ft_hour << 6) | t.ft_min) << 5) | t.ft_tsec)
  271. #define FTimeToUIntDate(t) ((((t.ft_year << 4) | t.ft_month) << 5) | t.ft_day)
  272. #define FTimeToULong(t) (((ulong)FTimeToUIntDate(t) << 16) |    \
  273.                                                  (ulong)FTimeToUIntTime(t))
  274.  
  275. uchar mksum(struct LzHead *h);
  276.  
  277. #ifdef  __TOS__
  278.  extern int argvmain (int, uchar **, uchar **);
  279.  
  280. static DTA _mydta;
  281. #endif __TOS__
  282. /*}}}  */
  283. /*{{{  setcrc:*/
  284.  
  285.  
  286. #ifndef __TOS__
  287. #define setcrc(h, crc) (*(uint *)(&(h)->Fname[1]+(h)->Fname[0])=(crc))
  288. #define getcrc(h)          (*(uint *)(&(h)->Fname[1]+(h)->Fname[0]))
  289. #else
  290. static void setcrc (struct LzHead *h, uint crc)
  291. {
  292.                 uchar *CrcPtr = &h->Fname[1] + h->Fname[0];
  293.  
  294.                 *CrcPtr++ = (uchar)(crc & 0xff);
  295.                 *CrcPtr++ = (uchar)(crc >> 8);
  296.                                 *CrcPtr++ = (uchar)(ThisSystem);    /* SystemId */
  297.                                 if (freezing==0) {
  298. /*                                *CrcPtr++ = (uchar) 0;
  299.                                   *CrcPtr++ = (uchar) 0; */
  300.                                 }
  301. }
  302. /*}}}  */
  303. /*{{{  getcrc:*/
  304.  
  305. static uint getcrc (struct LzHead *h)
  306. {
  307.                 uchar *CrcPtr = &h->Fname[1] + h->Fname[0];
  308.  
  309.                 return ((uint)*CrcPtr) | ((uint)*(CrcPtr + 1) << 8);
  310. }
  311. #endif
  312. /*}}}  */
  313. /*{{{  usage:             display helps*/
  314. /*******************************
  315.                 display helps
  316. *******************************/
  317. void usage(void)
  318. {
  319.   int i;
  320.   char *s,c;
  321.   s=use;
  322.   i=1;
  323.   while ( (c=*s++) != 0) {
  324.     if (c=='\n')
  325.        if (i++ == 24) {
  326.          fflush (stdin);                         /* wait for keystroke when used */
  327.          printf ("\n%s",M_PRESSKEY); /* with GEM-Desktop                        */
  328.          getch ();
  329.          putchar ('\n');
  330.          i=1;
  331.     }
  332.     putchar(c);
  333.   }
  334.   putchar ('\n');
  335.   longjmp (exit_jmp, 1);
  336. }
  337. /*}}}  */
  338. /*{{{  message:           Display a message*/
  339.  
  340. /*******************************
  341.                 display a message
  342. *******************************/
  343.  
  344. void message(uchar *p, uchar *q)
  345. {
  346.         if (flg_d == 0) {
  347.           printf("%s", p);
  348.           if (q) {
  349.                   printf(" : '%s'", q);
  350.           }
  351.           printf("\n");
  352.         }
  353. }
  354. /*}}}  */
  355. /*{{{  error:             process for an error*/
  356.  
  357. /*******************************
  358.         process for an error
  359. *******************************/
  360. void error(int errcode, uchar *p)
  361. {
  362.         if (copying) {                                          /* error during copying temporary? */
  363.                 fprintf(stderr, "\n%s\n", M_COPYERR);
  364.                 fclose(file1);
  365.                 unlink(arcname);                                /* erase incomplete archive */
  366.                 file1 = NULL;
  367.         }
  368.         fprintf(stderr, "\n%s", errmes[errcode]);
  369.         if (p) {
  370.                 fprintf(stderr, " : '%s'", p);
  371.         }
  372.         fprintf(stderr, "\n");
  373.         if (file3) {
  374.                 fclose(file3);
  375.                 if (!cmdupdate)                                 /* during extracting */
  376.                         unlink(pathname);                       /* delete the file */
  377.                         file3=NULL;
  378.         }
  379.         if (file1) {
  380.                 fclose(file1);
  381.                 if (cmdupdate)                                  /* during updating */
  382.                         rename(backup1, arcname);       /* recover old archive */
  383.         }
  384.         if (file2) {
  385.                 fclose(file2);
  386.                 if (!copying) {                                 /* if not copying */
  387.                         unlink(backup2);                        /* delete temporary */
  388.                         file2=NULL;
  389.                 }
  390.         }
  391.         if (copying)
  392.                 errorlevel = 3;
  393.         else
  394.                 errorlevel = 2;
  395.         longjmp (exit_jmp, 1);
  396. }
  397.  
  398. /*}}}  */
  399. /*{{{  userbreak:         handle user break*/
  400. /*******************************
  401.                 handle user break
  402. *******************************/
  403. #ifndef __TOS__
  404. void userbreak(void)
  405. {
  406.         error(CTRLBRK, NULL);
  407. }
  408. #endif
  409. /*}}}  */
  410. /*{{{  e_fopen:           fopen with detecting error*/
  411.  
  412. /*******************************
  413.         fopen with detecting error
  414. *******************************/
  415. FILE *e_fopen(uchar *fname, uchar *mode, int errID)
  416. {
  417.         FILE *f;
  418.  
  419.         if ((f = fopen(fname, mode)) == NULL) {
  420.                 if (errno == EACCES)
  421.                         error(RDONLY, fname);
  422.                 error(errID, fname);
  423.         }
  424.         return f;
  425. }
  426. /*}}}  */
  427. /*{{{  e_rename:          rename with detecting erorr*/
  428.  
  429. /*******************************
  430.         rename with detecting error
  431. *******************************/
  432. void e_rename(uchar *old, uchar *new)
  433. {
  434.         if (rename(old, new))
  435.                 error(RENAMEERR, old);
  436. }
  437. /*}}}  */
  438. /*{{{  getyn:             ask 'Y' or 'N'*/
  439. /*******************************
  440.                 ask 'Y' or 'N'
  441. *******************************/
  442. uint getyn(void)
  443. {
  444.         uint yn;
  445.  
  446.         do {
  447.                 yn = toupper(getch());
  448. #ifdef German
  449.         } while (yn != 'J' && yn != 'N');
  450. #else
  451.         } while (yn != 'Y' && yn != 'N');
  452. #endif
  453.         fprintf(stderr, "%c\n", yn);
  454. #ifdef German
  455.         if (yn == 'J') yn = 'Y';
  456. #endif
  457.         return yn;
  458. }
  459. /*}}}  */
  460. /*{{{  getynr:            ask 'Y', 'N' or 'R'*/
  461. /*******************************
  462.                 ask 'Y' or 'N'
  463. *******************************/
  464. uint getynr(void)
  465. {
  466.         uint yn;
  467.  
  468.         do {
  469.                 yn = toupper(getch());
  470. #ifdef German
  471.         } while (yn != 'J' && yn != 'N' && yn != 'R');
  472. #else
  473.         } while (yn != 'Y' && yn != 'N' && yn != 'R');
  474. #endif
  475.         fprintf(stderr, "%c\n", yn);
  476. #ifdef German
  477.         if (yn == 'J') yn = 'Y';
  478. #endif
  479.         return yn;
  480. }
  481. /*}}}  */
  482. /*{{{  extfn:             File name -> internal format*/
  483.  
  484. /*******************************
  485.   file name -> internal format
  486. *******************************/
  487. void extfn(uchar *p, uchar *pb)
  488. {
  489.         int i;
  490.         uchar * q;
  491.  
  492.         if ((q = strrchr(p, '\\')) != NULL ||
  493.                 (q = strchr(p, ':')) != NULL)
  494.                 p = q + 1;
  495.         q = p;
  496.         for (i = 8; i > 0; i--, pb++) {
  497.                 switch (*p) {
  498.                 case '*':
  499.                         *pb = '?';
  500.                         break;
  501.                 case '.':
  502.                 case '\0':
  503.                         *pb = ' ';
  504.                         break;
  505.                 default:
  506.                         *pb = *p++;
  507.                 }
  508.         }
  509.         while (+(*p != '\0' && *p++ != '.'));
  510.         for (i = 3; i > 0; i--, pb++) {
  511.                 switch (*p) {
  512.                 case '*':
  513.                         *pb = '?';
  514.                         break;
  515.                 case '\0':
  516.                         *pb = ' ';
  517.                         break;
  518.                 default:
  519.                         *pb = *p++;
  520.                 }
  521.         }
  522.         *q = *pb = '\0';
  523. }
  524. /*}}}  */
  525. /*{{{  packfn:            internal format -> file name*/
  526.  
  527. /*******************************
  528.   internal format -> file name
  529. *******************************/
  530. void packfn(uchar *p, uchar *q)
  531. {
  532.         int i;
  533.  
  534.         for (i = 8; i > 0; i--) {
  535.                 if (*q != ' ')
  536.                         *p++ = *q;
  537.                 q++;
  538.         }
  539.         *p++ = '.';
  540.         for (i = 3; i > 0; i--) {
  541.                 if (*q != ' ')
  542.                         *p++ = *q;
  543.                 q++;
  544.         }
  545.         if (p[-1] == '.')
  546.                 p--;
  547.         *p = '\0';
  548. }
  549. /*}}}  */
  550. /*{{{  backpath           get back to parent directory*/
  551. /*******************************
  552.   get back to parent directory
  553. *******************************/
  554. uchar *backpath(uchar *p)
  555. {
  556.         uchar *q;
  557.  
  558.         if ((q = strrchr(p, '\\')) == NULL &&
  559.                 (q = strchr(p, ':')) == NULL) {
  560.                 *p = '\0';
  561.                 q = p;
  562.         } else {
  563.                 *++q = '\0';
  564.         }
  565.         return q;
  566. }
  567. /*}}}  */
  568. /*{{{  tstpat :           whether path name was used or not*/
  569.  
  570. /***********************************
  571.   whether path name was used or not
  572. ***********************************/
  573. void tstpat(void)
  574. {
  575.         int i, cnt;
  576.         uchar path[MAXPATH];
  577.  
  578.         cnt = 0;
  579.         for (i = 0; i < patno; i++)
  580.                 cnt += patcnt[i];
  581.         if (cnt == 0)                                           /* no file matched */
  582.                 error(NOFILEERR, NULL);
  583.         for (i = 0; i < patno; i++) {
  584.                 if (patcnt[i] == 0) {                   /* if any path name was not used */
  585.                         packfn(stpcpy(path, patpath[i]), patfile[i]);
  586.                         fprintf(stderr, "%s : '%s'\n", M_NOMATCHERR, path);
  587.                         errorlevel = 1;                         /* display warning */
  588.                 }
  589.         }
  590. }
  591. /*}}}  */
  592. /*{{{  sethdr:            make a file header*/
  593.  
  594. /*******************************
  595.                 make a file header
  596. *******************************/
  597. void sethdr(uchar *fn, uint attr, struct LzHead *h)
  598. {
  599.         uint l;
  600.  
  601.         memset(h, 0, sizeof(struct LzHead));
  602.         l = (uint)strlen(fn);                                           /* length of file name */
  603.         h -> Fname[0] = l;
  604.         memcpy(h -> Fname + 1, fn, l);
  605.         l += 20 +  elen +2;                                        /* size of header */
  606.         h -> HeadSiz = l;
  607.         fseek(file3, 0L, SEEK_END);
  608.         h -> OrgSiz = textsize = ftell(file3);  /* original size of a file */
  609.         h -> PacSiz = codesize = 0;
  610.         method=FlgMethod;
  611. /*        if (h->OrgSiz < 5000 && FlgMethod==5) method=1; */
  612.         rewind(file3);
  613.         getftime(fileno(file3), &(h -> Ftime)); /* get time stamp */
  614.         h -> Attr = attr;                                       /* file attributes */
  615.         if (method==0) memcpy(h->HeadID,"-lz5-",5);
  616.         if (method==1) memcpy(h->HeadID,"-lh1-",5);
  617.             if (method==5) memcpy(h->HeadID,"-lh5-",5);
  618.             if (cmd== 'C') memcpy(h->HeadID,"-afx-",5);
  619. }
  620. /*}}}  */
  621. /*{{{  wthdr680x0:        write a file header on atari (or any system)*/
  622.  
  623. #ifdef __TOS__
  624. /*******************************
  625.         write a file header on
  626.         Atari ST (680x0)
  627. *******************************/
  628. int wthdr680x0 (register struct LzHead *h,
  629.                                 FILE *file)
  630. {
  631.         uchar buffer [256];
  632.         uchar chksum,*ptr2;
  633.         int comlen;
  634.         register uchar *ptr,*co,*ptr1;
  635.         union { uint x;
  636.                         uchar bytes [2]; } swap16;
  637.         union { ulong x;
  638.                         uchar bytes [4]; } swap32;
  639.  
  640.         register int i;
  641.         int len;
  642.         char c;
  643.  
  644.         if (comment[0] == 0) comlen = 0; else
  645.                            { comlen = 4 + strlen(comment);
  646.                              h->PacSiz += comlen; }
  647.         if (flg_s) yen2slash(&(h->Fname));
  648.         h -> HeadChk = mksum(h);                        /* header sum */
  649.  
  650.         ptr = buffer;
  651.         *ptr++ = h->HeadSiz;
  652.         *ptr++ = h->HeadChk;
  653.         for (i = 0; i < 5; i++)
  654.                 *ptr++ = h->HeadID [i];
  655.         swap32.x = h->PacSiz;
  656.         for (i = 3; i >= 0; i--)                 /* convert motorola --> intel */
  657.                 *ptr++ = swap32.bytes [i];
  658.         swap32.x = h->OrgSiz;
  659.         for (i = 3; i >= 0; i--)                 /* convert motorola --> intel */
  660.                 *ptr++ = swap32.bytes [i];
  661.         swap32.x = FTimeToULong (h->Ftime);
  662.         for (i = 3; i >= 0; i--)                 /* convert motorola --> intel */
  663.                 *ptr++ = swap32.bytes [i];
  664.         swap16.x  = h->Attr;
  665.         for (i = 1; i >= 0; i--)                 /* convert motorola --> intel */
  666.                 *ptr++ = swap16.bytes [i];
  667.         len = *ptr++ = h->Fname [0];
  668.         for (i = 1; i <= len + elen+2; i++) *ptr++ = h->Fname[i];
  669.         if (freezing && flg_k==0) {
  670.           ptr2=ptr-1;
  671.           if (comlen) {
  672.           ptr-=2;
  673.           *ptr++=comlen;
  674.           *ptr++=0;
  675.             *ptr++=0x3f;
  676.             co=comment;
  677.             while (*co) *ptr++=*co++;
  678.             *ptr++=0xff;
  679.             *ptr++=0x0;
  680.             *ptr++=0x0;
  681.           }
  682.           ptr1=&buffer[2];
  683.           chksum=0;
  684.           while (ptr1 != ptr2)
  685.              chksum = chksum + *ptr1++;
  686.           buffer[1]=chksum;
  687.           len = (int) fwrite (buffer, ptr-buffer  , 1, file);
  688.         } else
  689.           len = (int) fwrite (buffer, h->HeadSiz +2  , 1, file);
  690.  
  691.  
  692.         /* slash2yen(&(h->Fname)); */
  693.         h -> HeadChk = mksum(h);                        /* header sum */
  694.         return len;
  695. }
  696. #endif
  697. /*}}}  */
  698. /*{{{  wthdr:             write a file header*/
  699.  
  700. /*******************************
  701.         write a file header
  702. *******************************/
  703. void wthdr(struct LzHead *h)
  704. {
  705.         arcpos0 = ftell(file2);         /* memorize this position */
  706. #ifndef __TOS__
  707.         if (fwrite(h, h -> HeadSiz + 2, 1, file2) == 0)
  708.                 error(WTERR, backup2);
  709. #else
  710.         if (wthdr680x0 (h, file2) == 0)
  711.                 error(WTERR, backup2);
  712. #endif
  713. }
  714. /*}}}  */
  715. /*{{{  mksum:             calculate check-sum*/
  716. /*******************************
  717.   calculate check-sum of header
  718. *******************************/
  719. uchar umksum(struct LzHead *h)
  720. {
  721.         uchar *p, *q;
  722.         uchar i;
  723.  
  724.         p = (uchar *)h ;
  725.         q = p + h -> HeadSiz;
  726.         p+=2; q+=2;
  727.         for (i = 0; p < q; p++)
  728.                 i += *p;
  729.         return i;
  730. }
  731.  
  732. #ifndef __TOS__
  733. uchar mksum(struct LzHead *h)
  734. {
  735.         uchar *p, *q;
  736.         uchar i;
  737.  
  738.         p = (uchar *)h + 2;
  739.         q = p + h -> HeadSiz;
  740.         for (i = 0; p < q; p++)
  741.                 i += *p;
  742.         return i;
  743. }
  744. #else
  745. uchar mksum(struct LzHead *h)
  746. {
  747.         union { uint x;
  748.                         uchar bytes [2]; } swap16;
  749.         union { ulong x;
  750.                         uchar bytes [4]; } swap32;
  751.         char *s;
  752.         register uchar sum;
  753.         register int i;
  754.         int len;
  755.  
  756.         sum = 0;
  757.         for (i = 0; i < 5; i++)
  758.                 sum += h->HeadID [i];
  759.         swap32.x = h->PacSiz;
  760.         for (i = 3; i >= 0; i--)
  761.                 sum += swap32.bytes [i];
  762.         swap32.x = h->OrgSiz;
  763.         for (i = 3; i >= 0; i--)
  764.                 sum += swap32.bytes [i];
  765.         swap32.x = FTimeToULong (h->Ftime);
  766.         for (i = 3; i >= 0; i--)
  767.                 sum += swap32.bytes [i];
  768.         swap16.x = h->Attr;
  769.         for (i = 1; i >= 0; i--)
  770.                 sum += swap16.bytes [i];
  771.         sum += h->Fname [0];
  772.         len = (int) h->Fname [0];
  773.         s=h->Fname; s++;
  774.         for (i = 1; i <= h->HeadSiz - 20; i++)
  775.                 sum += *s++;
  776.  
  777.         return sum;
  778. }
  779. #endif
  780. /*}}}  */
  781. /*{{{  remkhdr:           remake file header and write*/
  782.  
  783. /*******************************
  784.         remake file header & write
  785. *******************************/
  786. void remkhdr(struct LzHead *h)
  787. {
  788.         int flg;
  789.         long arcpos1;
  790.  
  791.         flg = 0;
  792.         h -> PacSiz = codesize;                         /* packed size of a file */
  793.                 setcrc (h, crc);
  794.         flg_unpacked=0;
  795.         if (h -> OrgSiz <= codesize && flg_5==0) {          /* if packed size >= original size */
  796.                 flg = 1;                                                /* select method "simple copy" */
  797.                 flg_unpacked=1;
  798.                 memcpy(h->HeadID,"-lh0-",5);
  799.                 h -> PacSiz = h -> OrgSiz;
  800.         }
  801.         h -> HeadChk = mksum(h);                        /* header sum */
  802.  
  803.         if (flg_u && flg_5 == 0) {                                   /* without compression */
  804.                 crcflg=1; crc=0;
  805.                 copyfile(file3, file2, h -> OrgSiz);    /* do simple copy */
  806.                 flg = 0;
  807.                 setcrc(h,crc);
  808.         }
  809.         arcpos1 = ftell(file2);                         /* memorize this position */
  810.         fseek(file2, arcpos0, SEEK_SET);        /* seek to header */
  811. #ifndef __TOS__
  812.         fwrite(h, h -> HeadSiz + 2, 1, file2); /* rewrite header */
  813. #else
  814.         wthdr680x0 (h, file2);
  815. #endif
  816.         if (flg && flg_5 == 0) {
  817.                 rewind(file3);
  818.                 copyfile(file3, file2, h -> OrgSiz);    /* do simple copy */
  819.         } else {
  820.                 fseek(file2, arcpos1, SEEK_SET);                /* return to the end */
  821.         }
  822. }
  823. /*}}}  */
  824. /*{{{  rdhdr680x0:        read a file header on Atari*/
  825. #ifdef __TOS__
  826. /*******************************
  827.         read a file header on
  828.         Atari ST (680x0)
  829. *******************************/
  830. int rdhdr680x0 (register struct LzHead *h,
  831.                                 FILE *file)
  832. {
  833.         uchar buffer [sizeof (struct LzHead)];
  834.         register uchar *ptr;
  835.         union { uint x;
  836.                         uchar bytes [2]; } swap16;
  837.         union { ulong x;
  838.                         uchar bytes [4]; } swap32;
  839.         register int i;
  840.         int len;
  841.  
  842.         if ((h -> HeadSiz = getc (file)) <= 0 ||
  843.                 ferror (file) ||
  844.                 h->HeadSiz > sizeof buffer - 1 ||
  845.                 fread (buffer, (int) h->HeadSiz + 1, 1, file) == 0)
  846.          {
  847.                 return FAULT;
  848.          }
  849.  
  850.         ptr = buffer;
  851.         h->HeadChk = *ptr++;
  852.         for (i = 0; i < 5; i++)
  853.                 h->HeadID [i] = *ptr++;
  854.         for (i = 3; i >= 0; i--)                 /* convert intel --> motorola */
  855.                 swap32.bytes [i] = *ptr++;
  856.         h->PacSiz = swap32.x;
  857.         for (i = 3; i >= 0; i--)                 /* convert intel --> motorola */
  858.                 swap32.bytes [i] = *ptr++;
  859.         h->OrgSiz = swap32.x;
  860.         for (i = 3; i >= 0; i--)                 /* convert intel --> motorola */
  861.                 swap32.bytes [i] = *ptr++;
  862.         h->Ftime.ft_tsec  = (uint)(swap32.x & 0x1f);
  863.         h->Ftime.ft_min   = (uint)((swap32.x >>  5) & 0x3f);
  864.         h->Ftime.ft_hour  = (uint)((swap32.x >> 11) & 0x1f);
  865.         h->Ftime.ft_day   = (uint)((swap32.x >> 16) & 0x1f);
  866.         h->Ftime.ft_month = (uint)((swap32.x >> 21) & 0x0f);
  867.         h->Ftime.ft_year  = (uint)((swap32.x >> 25) & 0x7f);
  868.         for (i = 1; i >= 0; i--)                 /* convert intel --> motorola */
  869.                 swap16.bytes [i] = *ptr++;
  870.         h->Attr = swap16.x;
  871.         for (i=0;i<=MAXPATH;i++) h->Fname[i]=0;
  872.         len = h->Fname [0] = *ptr++;
  873.         for (i = 1; i <= h->HeadSiz - 20; i++)
  874.                 h->Fname [i] = *ptr++;
  875.  
  876.         return SUCCS;
  877. }
  878. #endif
  879. /*}}}  */
  880. /*{{{  gethdr :           get a file header*/
  881. /*******************************
  882.                 get a file header
  883. *******************************/
  884. uchar *gethdr(FILE *arc, struct LzHead *h)
  885. {
  886.         uchar *q,*p,*p1, i;
  887.         uint extsize;
  888.         char exthdr[256];
  889.         char fname[256];
  890.  
  891. #ifndef __TOS__
  892.         if ((h -> HeadSiz = getc(arc)) <= 0 ||
  893.                 h -> HeadSiz > sizeof(struct LzHead) - 3 ||
  894.                 fread(&(h -> HeadChk), h -> HeadSiz + 1, 1, arc) == 0)
  895.         {                                                               /* read file header */
  896.                 return NULL;
  897.         }
  898. #else
  899.         if (!rdhdr680x0 (h, arc))
  900.                 return NULL;
  901. #endif
  902.         if (mksum(h) != h -> HeadChk)
  903.            if (umksum(h) != h -> HeadChk) /* if sum is wrong */
  904.                  return NULL;
  905.         i = *(h -> Fname);
  906.         strncpy(filename, h -> Fname + 1, i);
  907.         *(filename + i) = '\0';
  908.  
  909.                 if ( (flg_k == 0) && UseExthdr) {
  910.           extsize=h->Fname[h->Fname[0]+4];
  911.           SystemId = h->Fname[h->Fname[0]+3];
  912.           comment[0] = 0; /* Prevent showing an illegal comment */
  913.           if (extsize != 0) {
  914.                 fread(exthdr,1,extsize-2,arc);
  915. /*                      h->PacSiz-=extsize;
  916.                         extsize=fgetc(arc);
  917.                         extsize+=(uint)fgetc(arc)<<8; */
  918.             while (extsize != 0) {
  919.                      if (exthdr[0] == 2) { /* pathname-header */
  920.                         p=fname; p1=&exthdr[1];
  921.                         while ( (*p++=*p1++) != 0xff);
  922.                         p--;
  923.                         *p++='\\';
  924.                         strcpy(p,filename);
  925.                         strcpy(filename,fname);
  926.                      }
  927.                      if (exthdr[0] == 0x3f) { /* Komment - Header */
  928.                        p=comment;p1=&exthdr[1];
  929.                        while ((*p++=*p1++) != 0xff); p--; *p=0;
  930.                      }
  931.  
  932.                            h->PacSiz-=extsize;
  933.                            extsize=fgetc(arc);
  934.                            extsize+=(uint)fgetc(arc)<<8;
  935.  
  936.                    if (extsize) {
  937.                  if (extsize > 250) {
  938.                    fseek(arc,extsize-2,SEEK_CUR); /* Header to long, skip */
  939.                    exthdr[0]=255; }
  940.                  else {
  941.                              fread(exthdr,1,extsize-2,arc);
  942.                               }
  943.                           }
  944.  
  945.            }
  946.          }
  947.                 }
  948.         if ((q = strrchr(filename, '\\')) == NULL &&
  949.             (q = strrchr(filename, '/')) == NULL  &&
  950.             (q = strchr(filename, ':')) == NULL)
  951.                 q = filename;
  952.         else
  953.                 q++;
  954.         return q;                                       /* return the portion of file name */
  955. }
  956. /*}}}  */
  957. /*{{{  matchpat:          test match of file name*/
  958. /*******************************
  959.         test match of file name
  960. *******************************/
  961. int matchpat(uchar *p)
  962. {
  963.         uchar buf[12], name[MAXPATH];
  964.         int i, j, retcode;
  965.  
  966.         retcode = FAULT;
  967.         strcpy(name, p);
  968.         extfn(name, buf);
  969.         for (i = 0; i < patno; i++) {
  970.                 if (flg_p || *patpath[i]) {     /* should compare full path ? */
  971.                         if (strcmp(name, patpath[i]))
  972.                                 continue;
  973.                 }
  974.                 for (j = 0; j < 11; j++) {              /* compare file name */
  975.                         if (patfile[i][j] != buf[j] && patfile[i][j] != '?')
  976.                         break;
  977.                 }
  978.                 if (j == 11) {                                  /* if matched */
  979.                         patcnt[i]++;
  980.                         retcode = SUCCS;
  981.                 }
  982.         }
  983.         return retcode;
  984. }
  985. /*}}}  */
  986. /*{{{  ratio:             ratio * 1000*/
  987. /*******************************
  988.                 ratio * 1000
  989. *******************************/
  990. uint ratio(ulong a, ulong b)
  991. {
  992.         int i;
  993.  
  994.         if (!b) return 0;                       /* if diviser == 0 */
  995.         for (i = 0; i < 3 && a < 0x19999999L; i++) {
  996.                 a *= 10;                                /* while not overflow */
  997.         }                                                       /* upto 1000 times */
  998.         for (; i < 3; i++) {            /* the case of overflow */
  999.                 b /= 10;
  1000.         }
  1001.         a += b / 2;                             /* for round up */
  1002.         return (uint)(a / b);           /* return (a * 1000 / b) */
  1003. }
  1004. /*}}}  */
  1005. /*{{{  cmpname:           compare names*/
  1006. /*******************************
  1007.                 compare names
  1008. *******************************/
  1009. int cmpname(uchar *f0, uchar *f1, uchar *p0, uchar *p1)
  1010. {
  1011.         int c;
  1012.  
  1013.         c = strcmp(f0, f1);                     /* compare only file names */
  1014.         if (c == 0) {
  1015.                 c = (int)(strlen(p0) - strlen(p1)); /* compare lengths of path names */
  1016.                 if (c == 0) {
  1017.                         c = strcmp(p0, p1);     /* compare path names */
  1018.                 }
  1019.         }
  1020.         return c;
  1021. }
  1022. /*}}}  */
  1023. /*{{{  regfile:           regist file names*/
  1024. /*******************************
  1025.         regist file names
  1026. *******************************/
  1027. int regfile(uchar *p, uchar *q, uchar *f, int attrib)
  1028. /*
  1029.         p: full path name including base directory
  1030.         q: directory name to be registed
  1031.         f: file name
  1032. */
  1033. {
  1034.         uchar path[MAXPATH];
  1035.         struct filebuf far *f0;
  1036.         struct filebuf far *f1;
  1037.         uchar *s;
  1038.         int c,size;
  1039.  
  1040.         if (flg_arc)
  1041.              if ((attrib & 0x20) == 0) return 0;
  1042.  
  1043.         if (strstr(f, "LHARC.)1(") || strstr(f, "LHARC.)2("))
  1044.                 return 0;                                 /* temporary file ? */
  1045.         stpcpy(stpcpy(path, q), f);
  1046.         stpcpy(s = stpcpy(fb1.dir, p), f);
  1047.         fb1.fpos = s - (uchar *)&fb1;
  1048.         fb1.cpos = flg_x ? (q - p) + (fb1.dir - (uchar *)&fb1) : fb1.fpos;
  1049.         if (fbuf == NULL) {                     /* for first entry */
  1050.         fbfiles=0;                              /* >> Number of files matched << */
  1051. #ifndef __TOS__
  1052.                 if (allocmem(fbsize = 0x100, &seg) != -1)
  1053.                         error(MEMOVRERR, NULL);
  1054.                 fbuf = (uchar far *)fbnxt = MK_FP(seg, 0);
  1055.                 fbleft = 0x100;
  1056.  
  1057. #else
  1058. /* >> get all the memory. fbmax holds the number of bytes available << */
  1059.                 fbsize=sizeof(struct filebuf) * MAXNUMFILES;
  1060.                 fbmax= (long) Malloc(-1);
  1061.                 fbuf = fbnxt = Malloc(fbmax);
  1062.                 if (fbuf == NULL)
  1063.                         error(MEMOVRERR, NULL);
  1064.                 fblft = fbmax;
  1065. #endif
  1066.                 *(long far *)fbuf = 0;
  1067.                 fbnxt += 4;
  1068.         }
  1069.         f0 = (struct filebuf far *)fbuf;
  1070.         do {                                    /* search position in which should be inserted*/
  1071.                 f1 = f0;
  1072.                 if ((f0 = f0 -> next) == NULL)
  1073.                         break;
  1074.                 fb0 = *f0;
  1075.                 c = cmpname((uchar *)&fb0 + fb0.fpos, (uchar *)&fb1 + fb1.fpos,
  1076.                                         (uchar *)&fb0 + fb0.cpos, (uchar *)&fb1 + fb1.cpos);
  1077.         } while (c < 0);
  1078.  
  1079.         if (f0 && c == 0 && strcmp(fb0.dir, fb1.dir)) {
  1080.                 error(DUPFNERR, (uchar *)&fb1 + fb1.cpos);
  1081.         }                                               /* same registing names of different files */
  1082.  
  1083.         if (f0 == NULL || c) {                          /* do regist */
  1084.                 size = (int)(strlen(fb1.dir) +
  1085.                                          (fb1.dir - (uchar *)&fb1)) + 1;
  1086. #ifndef __TOS__
  1087.                 if (fblft < sizeof(struct filebuf)) {   /* if buffer is short */
  1088.                         if (setblock(seg, fbsize += 0x100) != -1)
  1089.                                 error(TOOMANYERR, NULL);
  1090.                         fblft += 0x100;
  1091.                 }
  1092. #else
  1093.                 size += size & 1;               /* size must be even to avoid address error! */
  1094.                 if (fblft < sizeof (struct filebuf))
  1095.                         error(TOOMANYERR, NULL);
  1096. #endif
  1097.                 fb1.next = f0;
  1098.                 f0 = (struct filebuf far *)fbnxt;
  1099.                 f1 -> next = f0;
  1100.                 *f0 = fb1;
  1101.                 fblft -= size;
  1102.                 fbnxt += size;
  1103.                 fbfiles++;              /* >> Count files << */
  1104.         }
  1105.  return 1;
  1106. }
  1107. /*}}}  */
  1108. /*{{{  travel:            recursive collection of files*/
  1109. /*******************************
  1110.   recursive collection of files
  1111. *******************************/
  1112. int travel(uchar *p, uchar *q, uchar *f)
  1113. {
  1114.         struct ffblk ffb;
  1115.         static uchar buf[12];
  1116.         uchar *r, *s;
  1117.         int done, cnt, j;
  1118.  
  1119.         cnt = 0;
  1120.         if (flg_r == 1 || strrchr(q, '\\') == q + strlen(q) - 1) {
  1121.                 stpcpy(s = q + strlen(q), "*.*");
  1122.         }
  1123.         done = findfirst(p, &ffb, attr);        /* search the first file */
  1124.         s = backpath(q);
  1125.         while (! done) {
  1126.                 if (ffb.ff_attrib & 0x10) {     /* if this is a sub-directory */
  1127.                         if (ffb.ff_name[0] != '.') {
  1128.                                 r = stpcpy(stpcpy(s, ffb.ff_name), "\\");
  1129.                                 if (r - p > MAXPATH)
  1130.                                         error(TOOLONGERR, p);
  1131.                                 cnt += travel(p, q, f); /* search recursively */
  1132.                                 *s = '\0';
  1133.                         }
  1134.                 } else                                                  /* if this is a file */
  1135.                 if (flg_r == 2) {                               /* in /r2 mode */
  1136.                         cnt += regfile(p, q, ffb.ff_name,ffb.ff_attrib);                 /* regist name */
  1137.                 } else {                                                /* in /r+ mode */
  1138.                         stpcpy(s, ffb.ff_name);
  1139.                         extfn(s, buf);
  1140.                         for (j = 0; j < 11; j++) {                      /* test file names */
  1141.                                 if (f[j] != buf[j] && f[j] != '?')
  1142.                                 break;
  1143.                         }
  1144.                         if (j == 11) {
  1145.                                 cnt += regfile(p, q, ffb.ff_name,ffb.ff_attrib);         /* if match, regist */
  1146.                         }
  1147.                 }
  1148.                 done = findnext(&ffb);
  1149.         }
  1150.         return cnt;                                             /* number of registed files */
  1151. }
  1152. /*}}}  */
  1153. /*{{{  findfile:          non-recursive collection of files*/
  1154. /**********************************
  1155.  non-recursive collection of files
  1156. **********************************/
  1157. int findfile(uchar *p, uchar *q)
  1158. {
  1159.         struct ffblk ffb;
  1160.         int done, cnt;
  1161.  
  1162.         cnt = 0;
  1163.         done = findfirst(p, &ffb, attr);
  1164.         backpath(p);
  1165.         while (! done) {
  1166.                 cnt += regfile(p, q, ffb.ff_name,ffb.ff_attrib);
  1167.                 done = findnext(&ffb);
  1168.         }
  1169.         return cnt;
  1170. }
  1171. /*}}}  */
  1172. /*{{{  mklilst:           make file list to append*/
  1173. /*******************************
  1174.         make file lists to append
  1175. *******************************/
  1176. void mklist(void)
  1177. {
  1178.         uchar path[MAXPATH], *p, *q, *r;
  1179.         int i, cnt;
  1180.  
  1181.         Nfile = 0;
  1182.         if (flg_a) {                                            /* set attributes for search */
  1183.                 attr = 0x07;
  1184.         } else {
  1185.                 attr = 0;
  1186.         }
  1187.         if (flg_r) {
  1188.                 attr |= 0x10;
  1189.         }
  1190.         for (i = 0; i < patno; i++) {
  1191.                 p = patpath[i];
  1192.                 q = path;
  1193.                 if (*p && p[1] == ':') {                /* if path name includes drive */
  1194.                         q = stpcpy(path, p);                    /* ignore base directory */
  1195.                         r = path + 2;                                   /* don't regist drive name */
  1196.                 } else {
  1197.                         q = stpcpy(r = stpcpy(path, basedir), p);
  1198.                 }
  1199.                 if (flg_r == 1) {                               /* /r+ mode */
  1200.                         cnt = travel(path, r, patfile[i]);
  1201.                 } else if (flg_r > 1) {                 /* /r2 mode */
  1202.                         packfn(q, patfile[i]);
  1203.                         cnt = travel(path, r, NULL);
  1204.                 } else {                                                /* /r- mode */
  1205.                         packfn(q, patfile[i]);
  1206.                         cnt = findfile(path, r);
  1207.                 }
  1208.                 Nfile += patcnt[i] = cnt;
  1209.         }
  1210.  
  1211. #ifdef __TOS__
  1212. /* >> After registering all files, free the unused memory << */
  1213.         Mshrink(0,fbuf,fbmax-fblft+5);
  1214.         if (flg_d == 0) printf("Files matched: %ld\n",fbfiles);
  1215. #endif
  1216. }
  1217. /*}}}  */
  1218. /*{{{  mkhdr:             make file header*/
  1219. /*******************************
  1220.                 make file header
  1221. *******************************/
  1222. uchar *mkhdr(struct filebuf far *f, struct LzHead *h)
  1223. {
  1224.         int attr;
  1225.  
  1226.         fb0 = *f;
  1227.         attr = getfattr(fb0.dir);
  1228.         file3 = e_fopen(fb0.dir, "rb", RDERR);
  1229.  
  1230.         sethdr((uchar *)&fb0 + fb0.cpos, attr, h);
  1231.         return (uchar *)&fb0 + fb0.fpos;        /* position of file name */
  1232. }
  1233.  
  1234. extern uint blkcnt;
  1235. uint curcnt;
  1236. uint nxtcnt;
  1237. /*}}}  */
  1238. /*{{{  blkdisp:           calculate and display*/
  1239. /*******************************
  1240.         calculate and display
  1241.                 for indicator
  1242. *******************************/
  1243.  
  1244. void blkdisp(long l, char *s) {
  1245.         uint i;
  1246.  
  1247.         if (flg_n == 0) {
  1248.                 blocksize=4096;
  1249.                 printf("\n  %s :  ", s);
  1250.                 blkcnt = (uint)((l + 4095) / 4096);
  1251.                 if (blkcnt > MAXBLK) {
  1252.                         blkcnt = MAXBLK;
  1253.                         blocksize= l / MAXBLK;
  1254.                 }
  1255.                 i = blkcnt;
  1256.                 while (i-- > 0) {
  1257.                         putchar('.');
  1258.                 }
  1259.                 printf("\r   %s :  ", s);
  1260.                 curcnt = nxtcnt = 0;
  1261.         } else {
  1262.                 curcnt = 0;
  1263.                 nxtcnt = -1;
  1264.         }
  1265. }
  1266. /*}}}  */
  1267. /*{{{  curback:           let cursor back after displaying indicator*/
  1268.  
  1269. /*******************************
  1270.         let cursor back after
  1271.         displaying indicator
  1272. *******************************/
  1273. void curback(void)
  1274. {
  1275.         if (flg_n == 0) {
  1276.                 printf("\r  ");
  1277.         }
  1278. }
  1279. /*}}}  */
  1280. /*{{{  MKinputbuf:        make buffers for reading*/
  1281.  
  1282. /* Try to read the complete file. If the position is odd, begin reading at */
  1283. /* an even position and dicard one byte                                    */
  1284.  
  1285. void MKinputbuf(long filesize)
  1286. {
  1287.    long bufsize;
  1288.    long Pos;
  1289.  
  1290.        bufsize=(long)Malloc(-1)-50000;
  1291.    if (bufsize < 0) bufsize=8192;
  1292.    bufsize=min(filesize,bufsize)+1024;
  1293.    TheInputBuf=(char *) Malloc(bufsize+2);
  1294.    if (TheInputBuf < 0) error(MEMOVRERR,NULL);
  1295.    if (TheInputBuf>0) {
  1296.       if ((bufsize & 1) == 1) bufsize--;        /* Make bufsize even */
  1297.       if ((ftell(infile) & 1) == 1) {           /* Odd position     */
  1298.           fseek(infile,ftell(infile)-1,0);         /* go to even pos.   */
  1299.           setvbuf(infile,TheInputBuf,   _IOFBF, bufsize); /* set buffer */
  1300.           getc(infile);                         /* fill buffer, dicard char */
  1301.        } else
  1302.        {   fseek(infile,ftell(infile),0);           /* even position is ok */
  1303.            setvbuf(infile,TheInputBuf,  _IOFBF, bufsize);
  1304.        }
  1305.        FileFits=1;                               /* signal file fits into mem */
  1306.    } else FileFits=0;
  1307.  
  1308.  
  1309. }
  1310. /*}}}  */
  1311. /*{{{  mkoutboutb         Make buffers for writing*/
  1312.  
  1313. void MKoutputbuf( void )
  1314. {
  1315.    long bufsize;
  1316.    char *start,ende;
  1317.    bufsize=(long)Malloc(-1)-20000;
  1318.    TheOutputBuf=Malloc(bufsize);
  1319.    fseek(outfile,ftell(outfile),0);
  1320.    if (TheOutputBuf>0) {
  1321.         setvbuf(outfile,TheOutputBuf,_IOFBF,bufsize);
  1322.     } else {
  1323.         setvbuf(outfile,buf3,_IOFBF,BUFFERSIZ);
  1324.     }
  1325. }
  1326. /*}}}  */
  1327. /*{{{  freeze:            freeze a file*/
  1328.  
  1329.  
  1330. /*******************************
  1331.                 freeze a file
  1332. *******************************/
  1333. void freeze(uchar *p)
  1334. {
  1335.         char *hp;
  1336.         char iname[128];
  1337.         if (FTimeToULong (arcstamp) < FTimeToULong (Hdr2.Ftime))
  1338.                 arcstamp = Hdr2.Ftime;
  1339.         strcpy(iname,p);
  1340.  
  1341.     freezing=1;
  1342.     if (flg_d == 0) printf("%s ", p);
  1343.     if (flg_e) { /* Enter comment THQ */
  1344.             printf("\n");
  1345.         printf(M_COMMENT);
  1346.         gets(comment);
  1347.     }
  1348.  
  1349.     if (method!=5)
  1350.                 blkdisp(Hdr2.OrgSiz,   "Freezing ");
  1351.         else
  1352.         blkdisp(Hdr2.OrgSiz/2, "Freezing ");
  1353.  
  1354.  
  1355.     wthdr(&Hdr2);
  1356.         if (method == 5) init_encode5();
  1357.         setvbuf(file3, buf3, _IOFBF, BUFFERSIZ);
  1358.         infile = file3;
  1359.         outfile = file2;
  1360.         MKinputbuf(Hdr2.OrgSiz);
  1361.         infname = p;
  1362.         textsize = Hdr2.OrgSiz;
  1363.         crc = 0;
  1364.             codesize=0;
  1365.         if (flg_u) codesize = Hdr2.OrgSiz + 1; else {
  1366.                 if (method==0) EncodeOld();
  1367.                 if (method==1) Encode();
  1368.                 if (method==5) codesize=encode5(Hdr2.OrgSiz);
  1369.         }
  1370.         fflush(outfile);
  1371.  
  1372.         fseek(infile,ftell(infile),0);
  1373.         setvbuf(file3,buf3,_IOFBF,BUFFERSIZ);
  1374.         fseek(file2,0,SEEK_END);
  1375.  
  1376.         Mfree(TheInputBuf);
  1377.  
  1378.         if (flg_backup)
  1379.              Fattrib(iname,1,Fattrib(iname,0,0) & 0xff-0x20);
  1380.         remkhdr(&Hdr2);
  1381.         curback();
  1382.         if (flg_d == 0) printf("Frozen(%3d%%) \n", ratio(Hdr2.PacSiz, Hdr2.OrgSiz) / 10);
  1383.         comment[0] = 0;
  1384.         freezing=0;
  1385. }
  1386. /*}}}  */
  1387. /*{{{  copyold:           copy file from old archiv*/
  1388.  
  1389.  
  1390. /*******************************
  1391.                 Copy a file from
  1392.                         old archive
  1393. *******************************/
  1394. void copyold(void)
  1395. {
  1396.         if (FTimeToULong (arcstamp) < FTimeToULong (Hdr1.Ftime))
  1397.                 arcstamp = Hdr1.Ftime;
  1398.         wthdr(&Hdr1);                           /* copy from old archive */
  1399.         copyfile(file1, file2, Hdr1.PacSiz);
  1400. }
  1401. /*}}}  */
  1402. /*{{{  execappend:        execute one of a, u, m commands*/
  1403.  
  1404. /*******************************
  1405.         execute one of a, u, m
  1406.                 commands
  1407. *******************************/
  1408. int execappend(void)
  1409. {
  1410.         struct filebuf far *f0;
  1411.         uchar *p, *q;
  1412.         int c, d;
  1413.         int cnt = 0;
  1414.  
  1415.         q = file1 ? gethdr(file1, &Hdr1) : NULL;        /* read header from old arc */
  1416.         if ((f0 = ((struct filebuf far *)fbuf) -> next) != NULL) {
  1417.                 p = mkhdr(f0, &Hdr2);                   /* make header from the file list */
  1418.         }
  1419.         while (1) {
  1420.                 if (f0 == NULL) {
  1421.                         d = 1;
  1422.                         if (q == NULL)
  1423.                                 break;
  1424.                 } else if (q == NULL) {
  1425.                         d = -1;
  1426.                 } else {
  1427.                         d = cmpname(p, q, (uchar *)&fb0 + fb0.cpos, filename);
  1428.                 }
  1429.                 c = d;
  1430.                 if (c == 0) {
  1431.                         if (flg_c || FTimeToULong (Hdr1.Ftime) <
  1432.                                                  FTimeToULong (Hdr2.Ftime)) {
  1433.                                 c = -1;
  1434.                         } else {
  1435.                                 c = 1;
  1436.                         }
  1437.                 }
  1438.                 if (c < 0) {                                    /* freeze a new file */
  1439.                         if (d == 0) {
  1440.                                 fseek(file1, Hdr1.PacSiz, SEEK_CUR);
  1441.                                 q = gethdr(file1, &Hdr1);               /* skip a file in old */
  1442.                         }                                                                       /* archive */
  1443.                         freeze(fb0.dir);
  1444.                         fclose(file3);
  1445.                         cnt++;
  1446.                         if ((f0 = fb0.next) != NULL) {          /* make header of the next */
  1447.                                 p = mkhdr(f0, &Hdr2);                   /* file in file list */
  1448.                         }
  1449.                 } else {                                                /* copy a file from old archive */
  1450.                         if (d == 0) {
  1451.                                 fclose(file3);
  1452.                                 if ((f0 = fb0.next) != NULL) {  /* make header of the next */
  1453.                                         p = mkhdr(f0, &Hdr2);           /* file in file list */
  1454.                                 }
  1455.                         }
  1456.                         copyold();
  1457.                         q = gethdr(file1, &Hdr1);                       /* get the next header */
  1458.                 }                                                                               /* in old archive */
  1459.         }
  1460.         return cnt;
  1461. }
  1462. /*}}}  */
  1463. /*{{{  delfile:           delete files after execution of updating in 'm' command*/
  1464.  
  1465. /*******************************
  1466.         delete files after
  1467.         execution of updating
  1468.         in 'm' command
  1469. *******************************/
  1470. void delfile(void)
  1471. {
  1472.         struct filebuf far *f0;
  1473.         struct filebuf fb0;
  1474.  
  1475.         f0 = (struct filebuf far *)fbuf;
  1476.         while ((f0 = f0 -> next) != NULL) {
  1477.                 fb0 = *f0;
  1478.                 unlink(fb0.dir);
  1479.         };
  1480. }
  1481. /*}}}  */
  1482. /*{{{  openarc1:          open an old archiv*/
  1483.  
  1484. /*******************************
  1485.         open an old archive
  1486. *******************************/
  1487. void openarc1(void)
  1488. {
  1489.         uchar *p, *q;
  1490.  
  1491.         file1 = e_fopen(infname = arcname, "rb", NOARCERR);
  1492. /* >> Because some SFX-Versions for the ST have a header bigger 2048 Bytes
  1493.       4096 bytes are read here << */
  1494.         q = buf2 - 5 + fread(buf2, 1, 4096, file1);
  1495.         for (p = buf2; p < q; p++) {
  1496.                 if (p[0] == '-' && p[4] == '-')
  1497.                  if (p[1] == 'l' || p[1] == 'a') break;
  1498.         }
  1499.         if (p >= q) {
  1500.                 error(NOFILEERR, arcname);
  1501.         }
  1502.         fseek(file1, (long)(p - buf2 - 2), SEEK_SET);
  1503. }
  1504. /*}}}  */
  1505. /*{{{  openrwarc1:        open an archiv in rd/wt for testing read-only*/
  1506.  
  1507. /*******************************
  1508.         open an archive in rd/wt
  1509.         for testing read-only
  1510. *******************************/
  1511. void openrwarc1(void)
  1512. {
  1513.         file1 = e_fopen(arcname, "r+b", NOARCERR);
  1514. }
  1515. /*}}}  */
  1516. /*{{{  openbackup1        close an old archiv & rename to temporary*/
  1517. /*******************************
  1518.         close an old archive
  1519.         & rename to temporary
  1520. *******************************/
  1521. static void openbackup1(void)
  1522. {
  1523.         fclose(file1);
  1524.         stpcpy(backpath(strcpy(backup1, arcname)), "lharc.)1(");
  1525.         e_rename(arcname, backup1);
  1526.         file1 = fopen(infname = backup1, "rb");
  1527. }
  1528. /*}}}  */
  1529. /*{{{  openbackup2        open a temporary file for a new archiv*/
  1530. /*******************************
  1531.         open a temporary file
  1532.         for a new archive
  1533. *******************************/
  1534. static void openbackup2(void)
  1535. {
  1536.         if (flg_w) {
  1537.                 stpcpy(stpcpy(backup2, workdir), "lharc.)2(");
  1538.         } else {
  1539.                 strcat(backpath(strcpy(backup2, arcname)), "lharc.)2(");
  1540.         }
  1541.         file2 = e_fopen(outfname = backup2, "w+b", MKTMPERR);
  1542.         setvbuf(file2, buf2, _IOFBF, BUFFERSIZ);
  1543. }
  1544. /*}}}  */
  1545. /*{{{  stclosearc:        set time & close an archive*/
  1546. /*******************************
  1547.    set time & close an archive
  1548. *******************************/
  1549. void stclosearc(FILE *f)
  1550. {
  1551.         if (flg_t) {
  1552.                 fflush(f);
  1553.                 setftime(fileno(f), &arcstamp);
  1554.         }
  1555.         fclose(f);
  1556. }
  1557. /*}}}  */
  1558. /*{{{  endofupdate        end-of-job process in making new archive*/
  1559.  
  1560. /*******************************
  1561.         end-of-job process
  1562.         in making new archive
  1563. *******************************/
  1564. void endofupdate(int cnt)
  1565. {
  1566.         if (file1)
  1567.                 stclosearc(file1);
  1568.         tstpat();
  1569.         if (cnt) {                                      /* if any files are manipulated */
  1570.                 if (file1)
  1571.                         if (unlink(backup1))            /* delete an old archive */
  1572.                                 printf("debug : Failed in deleting '%s'.", backup1);
  1573.                 if ((arcpos0 = ftell(file2)) != 0) {
  1574.                         if (putc(0, file2) == EOF)
  1575.                                 error(WTERR, backup2);
  1576.                         if (flg_w) {                    /* if work directory is assigned */
  1577.                                 rewind(file2);
  1578.                                 infname = backup2;
  1579.                                 copying = 1;                    /* copy temporary to new archive */
  1580.                                 file1 = e_fopen(outfname = arcname, "wb", MKFILEERR);
  1581.                                 if (flg_d == 0) printf("Copying Temp to Archive ...");
  1582.                                 copyfile(file2, file1, arcpos0 + 1);
  1583.                                 if (flg_d == 0) printf("\n");
  1584.                                 copying = 0;
  1585.                                 stclosearc(file1);
  1586.                                 fclose(file2);
  1587.                                 unlink(backup2);
  1588.                         } else {
  1589.                                 stclosearc(file2);      /* else rename temporary to archive */
  1590.                                 rename(backup2, arcname);
  1591.                         }
  1592.                 } else {
  1593.                         fclose(file2);
  1594.                         unlink(backup2);
  1595.                 }
  1596.         } else {                                        /* if no change was made in archive */
  1597.                 fclose(file2);
  1598.                 unlink(backup2);
  1599.                 rename(backup1, arcname);       /* restore the old archive */
  1600.         }
  1601. }
  1602. /*}}}  */
  1603. /*{{{  append:            a,u,m command*/
  1604. /*******************************
  1605.                 a, u, m command
  1606. *******************************/
  1607. void append(void)
  1608. {
  1609.         int cnt;
  1610.  
  1611.         file1 = fopen(arcname, "r+b");
  1612.         if (file1) {
  1613.                 openbackup1();                          /* if archive presents, rename to temp */
  1614.         } else {
  1615.                 if (errno == EACCES)
  1616.                         error(RDONLY, arcname); /* read-only error */
  1617.         }
  1618.         mklist();                                               /* make a file list */
  1619.         if (Nfile == 0) {
  1620.                 error(NOFILEERR, NULL);
  1621.         }
  1622.         if (file1) {
  1623.                 message("Updating archive", arcname);
  1624.         } else {
  1625.                 message("Creating archive", arcname);
  1626.         }
  1627.         openbackup2();                                  /* open temporary for new archive */
  1628.         cnt = execappend();                     /* execute updating archive */
  1629.         endofupdate(cnt);                               /* end-of-job process */
  1630.         if (cmd == 'M')
  1631.                 delfile();                                      /* if 'm' command, delete files */
  1632. #ifndef __TOS__
  1633.         freemem(seg);
  1634. #else
  1635.         free (fbuf);
  1636. #endif
  1637. }
  1638. /*}}}  */
  1639. /*{{{  open_afxb:         open backup-file for afx*/
  1640. void open_afxbackup(char *s)
  1641. {
  1642.   char *p,*d,c;
  1643.   p=backup2; d=p; *backup2='\0';
  1644.   while ( (c=*s++) != 0) {
  1645.     if ((c=='\\') || (c==':'))
  1646.         d=p+1;
  1647.     *p++=c;
  1648.   }
  1649.   strcpy(d,"__temp__.lzs");
  1650.   file2=e_fopen(outfname=backup2,"w+b",MKTMPERR);
  1651.   setvbuf(file2,buf2,_IOFBF,BUFFERSIZ);
  1652. }
  1653. /*}}}  */
  1654. /*{{{  pack_aafx:         subprocess in packing afx*/
  1655. void pack_aafx(void)
  1656. {
  1657.         struct filebuf far *f0;
  1658.         uchar *p, *q;
  1659.         int c, d;
  1660.         int cnt = 0;
  1661.         if ((f0 = ((struct filebuf far *)fbuf) -> next) != NULL) {
  1662.                 p = mkhdr(f0, &Hdr2);                   /* make header from the file list */
  1663.         }
  1664.         while (f0 != NULL) {
  1665.                         switch(test_afx(fb0.dir)) {
  1666.                            case 0: open_afxbackup(fb0.dir);
  1667.                                            freeze(fb0.dir);
  1668.                                fclose(file3);
  1669.                        fclose(file2);
  1670.                        if (flg_unpacked==0) {
  1671.                           unlink(fb0.dir);
  1672.                           if (rename(backup2,fb0.dir) != 0)
  1673.                               error(RENAMEERR, fb0.dir);
  1674.                        } else
  1675.                          unlink(backup2);
  1676.                        break;
  1677.                            case 1: printf("%s\n  already in AFX-format\n",fb0.dir);      break;
  1678.                            case 2: printf("%s\n  already in LHarc-format\n",fb0.dir);    break;
  1679.                            case 3: printf("%s\n  Program-file\n",fb0.dir);                           break;
  1680.                         }
  1681.                     if (file2 != NULL) fclose(file2);
  1682.                         if (file3 != NULL) fclose(file3);
  1683.             cnt++;
  1684.             if ((f0 = fb0.next) != NULL) {          /* make header of the next */
  1685.                     p = mkhdr(f0, &Hdr2);           /* file in file list */
  1686.             }
  1687.         }
  1688.         return cnt;
  1689. }
  1690. /*}}}  */
  1691. /*{{{  pack_afx:          pack-afx*/
  1692. void pack_afx(void)
  1693. {
  1694.         int cnt;
  1695.         char *p;
  1696.  
  1697.         mklist();                                               /* make a file list */
  1698.         if (Nfile == 0) {
  1699.                 error(NOFILEERR, NULL);
  1700.         }
  1701.         FlgMethod=0;
  1702.         pack_aafx();
  1703. #ifndef __TOS__
  1704.         freemem(seg);
  1705. #else
  1706.         free (fbuf);
  1707. #endif
  1708. }
  1709. /*}}}  */
  1710. /*{{{  freshen:           f command*/
  1711. /*******************************
  1712.                 f command
  1713. *******************************/
  1714. void freshen(void)
  1715. {
  1716.         uchar path[MAXPATH];
  1717.         int c;
  1718.         int cnt = 0;
  1719.  
  1720.         openrwarc1();                                           /* open an archive */
  1721.         message("Freshening archive", arcname);
  1722.         openbackup1();                                          /* rename the archive to temp. */
  1723.         openbackup2();                                          /* open temp. for a new archive */
  1724.         while (gethdr(file1, &Hdr1)) {
  1725.                 c = 0;
  1726.                 if (matchpat(filename)) {
  1727.                         stpcpy(stpcpy(path, basedir), filename);
  1728.                         if ((file3 = fopen(path, "rb")) != NULL) {
  1729.                                 sethdr(filename, getfattr(path), &Hdr2);
  1730.                                 if (flg_c || FTimeToULong (Hdr1.Ftime) <
  1731.                                                          FTimeToULong (Hdr2.Ftime)) {
  1732.                                         c = 1;                          /* found the file to be updated */
  1733.                                 }
  1734.                         }
  1735.                 }
  1736.                 if (c) {
  1737.                         freeze(path);                           /* do updating */
  1738.                         cnt++;
  1739.                         fseek(file1, Hdr1.PacSiz, SEEK_CUR);
  1740.                 } else {
  1741.                         copyold();
  1742.                 }
  1743.                 if (file3)
  1744.                         fclose(file3);
  1745.         }
  1746.         endofupdate(cnt);                                       /* end-of-job process */
  1747. }
  1748. /*}}}  */
  1749. /*{{{  tstdir:            test the file which should be melted*/
  1750. /*******************************
  1751.         test the file which
  1752.         should be melted
  1753. *******************************/
  1754. int tstdir(uchar *name)
  1755. {
  1756.         uchar path[MAXPATH], *p, yn;
  1757.         struct ffblk ffb;
  1758. Again:
  1759.         p = name;
  1760.  
  1761.         if (*p && p[1] == ':')                          /* skip a drive name */
  1762.                 p += 2;
  1763.         if (*p == '\\')                                         /* skip a root mark('\') */
  1764.                 p++;
  1765.         yn = flg_m ? 'Y' : 'N';
  1766.         while ((p = strchr(p, '\\')) != NULL) { /* skip to next '\' */
  1767.                 memcpy(path, name, p - name);
  1768.                 path[p - name] = '\0';
  1769.                 if (findfirst(path, &ffb, 0x1f)) {      /* Is there this directory? */
  1770.                         if (yn == 'N') {
  1771.                                 printf("'%s' : %s", name, M_MKDIR);
  1772.                                 yn = getyn();
  1773.                         }
  1774.                         if (yn == 'N') {
  1775.                                 return FAULT;
  1776.                         } else {
  1777.                                   if (strcmp(path,".") != 0)
  1778.                                   if (mkdir(path)) {                      /* make directory */
  1779.                                          error(MKDIRERR, path);
  1780.                                 }
  1781.                         }
  1782.                 } else {
  1783.                         if ((ffb.ff_attrib & 0x10) == 0) {
  1784.                                 error(MKDIRERR, path);  /* if the name isn't directory */
  1785.                         }
  1786.                 }
  1787.                 p++;
  1788.         }
  1789.         if (! findfirst(name, &ffb, 0x1f)) {    /* if a file has the same name */
  1790.                 if (ffb.ff_attrib & 0x01 && ffb.ff_attrib != Hdr1.Attr) {
  1791.                                                                 /* if the file is read-only, */
  1792.                                                                 /* attributes must match */
  1793.                         fprintf(stderr, "'%s' %s\n", M_RDONLY);
  1794.                         return FAULT;
  1795.                 }
  1796.                 yn = 'Y';
  1797. #ifdef __TOS__
  1798.                 if (flg_c == 0 && UnixFile == 0) {
  1799. #else
  1800.                 if (flg_c == 0) {
  1801. #endif
  1802.                         if (((ulong)ffb.ff_fdate << 16) + (ulong)ffb.ff_ftime
  1803.                                         < FTimeToULong (Hdr1.Ftime)) {  /* compare time stamps */
  1804.                                 yn = 'Y';
  1805.                         } else {
  1806.                                 printf("Skipped : '%s' : New or same file exists.\n", name);
  1807.                                 yn = 'N';
  1808.                         }
  1809.                 }
  1810.                 if (yn == 'Y' && flg_m == 0) {
  1811.                         fprintf(stderr, "'%s' : %s", name, M_OVERWT);
  1812.                         yn = getynr();                           /* may overwrite? */
  1813.                         if (yn == 'R') {
  1814.                            printf(M_ENTERNEW);
  1815.                            scanf("%s",name);
  1816.                            goto Again;
  1817.                         }
  1818.                 }
  1819.                 if (yn == 'N') {
  1820.                         return FAULT;
  1821.                 }
  1822.                 setfattr(name, 0x20);                   /* reset attributes */
  1823.         }
  1824.         return SUCCS;
  1825. }
  1826. /*}}}  */
  1827. /*{{{  tstID:             read header-ID (method)*/
  1828. /*******************************
  1829.         read header-ID (method)
  1830. *******************************/
  1831. int tstID(uchar *h)
  1832. {
  1833.         int m;
  1834.         static uchar IDpat[6][6] =
  1835.                 {"-lz4-", "-lz5-", "-lh0-", "-lh1-","-lh5-","-afx-"};
  1836.                                 /*  0        1        2        3       4       5   */
  1837.         m = (int)((sizeof IDpat) / (sizeof IDpat [0]));
  1838.         while (m >= 0 && memcmp(h, IDpat[m], 5)) {
  1839.                 m--;
  1840.         }
  1841.         if (m==5) m=1;
  1842.         return m;
  1843. }
  1844. /*}}}  */
  1845. /*{{{  Dos1File:          Dateiname nach 8+3 Zeichen wandeln*/
  1846. #ifdef __TOS__
  1847.  
  1848. char LegalChar(char c)
  1849. {
  1850.   if (c <= 32) return 0;
  1851.   if (c == '*' || c == '?') return 0;
  1852.   return 1;
  1853. }
  1854.  
  1855. char *Dos1File(char *s, char *d) /* Ein Dateiname ohne Ordner wird überprüft */
  1856. {
  1857.   char c,*t;
  1858.   int p;
  1859.   int l;
  1860.   int i;
  1861.   int j;
  1862.   int k;
  1863.   int m;
  1864.  
  1865.   /* Suche von hinten den letzten Punkt. i ist die Position des
  1866.      letzten Zeichens vor der Extension                         */
  1867.  
  1868.      l = strlen(s);
  1869.      for (i=l; i>=0;i--) if (s[i] == '.') break;
  1870.      m = i-1;
  1871.      if (i<=0) m = l;
  1872.  
  1873.   /* Kopiere maximal 8 Zeichen des Dateinamens. Überspringe Punkte
  1874.      und illegale Zeichen */
  1875.  
  1876.      j = 0; k = 0;
  1877.      t=s;
  1878.      for (j = 0; j<=7; j++) {
  1879.         c = *t++;
  1880.         if (i>0) if (k++>i)  break;
  1881.         if (c=='\0') break;
  1882.         if (j > m)   break;
  1883.         if (c != '.' && c > 32 && c != ':') {
  1884.                 if (LegalChar(c)) *d++ = c;}
  1885.          else j--;
  1886.      }
  1887.      if (i>0) {
  1888.         *d++ = '.';
  1889.         i++;
  1890.         for (j=0; j<=2; j++) {
  1891.            c=s[i++];
  1892.            if (c==0) break;
  1893.            if (c > 32 && c != ':') if (LegalChar(c)) *d++ = c;
  1894.         }
  1895.      }
  1896.      *d='\0';
  1897.      return d;
  1898. }
  1899. /*}}}  */
  1900. /*{{{  DosFile:           File mit Ordnername nach 8+3 wandeln*/
  1901. /* Auftrennen des Files in einzelne Ordner (falls nötig) und anpassung
  1902.    jedes Ordners an 8+3 Zeichen */
  1903. void DosFile(char *s)
  1904. {
  1905.   char file[128], *f=file;
  1906.   char dest[128], *d=dest;
  1907.   char c,*s1=s;
  1908.   *d=0;
  1909.   while (( c= *s++) != 0) {
  1910.     if (c=='/') c = '\\';
  1911.     if (c==':' || c == '\\') {
  1912.       *d=0;
  1913.       f=Dos1File(dest,f);
  1914.       *f++=c; *f='\0';
  1915.       d=dest;
  1916.     } else *d++=c;
  1917.   }
  1918.   *d=0;
  1919.   f=Dos1File(dest,f);
  1920.   strcpy(s1,file);
  1921. }
  1922. #endif
  1923. /*}}}  */
  1924. /*{{{  extract:           a,x,p,t command*/
  1925.  
  1926. /*******************************
  1927.                 e, x, p, t command
  1928. *******************************/
  1929. int extract(void)
  1930. {
  1931.         uchar *p, *q;
  1932.         int m;
  1933.         int cnt = 0;
  1934.  
  1935.         openarc1();                                             /* open an archive */
  1936.         setvbuf(file1, buf2, _IOFBF, 1024);
  1937.         message("Extract from", arcname);
  1938.         if (flg_v == 1)
  1939.                 fprintf(file3, "Extract from '%s'\n", arcname);
  1940.         UseExthdr=1;
  1941.         while ((p = gethdr(file1, &Hdr1)) != NULL) {
  1942.  
  1943.                 if (matchpat(filename)) {
  1944.                         arcpos0 = ftell(file1) + Hdr1.PacSiz;
  1945.                          infile=file1;
  1946.                         MKinputbuf(Hdr1.PacSiz);
  1947.                         if (cmd == 'E') {                       /* if extract command, */
  1948.                                 if (flg_x) {                    /* get the destination path name */
  1949.                                         p = stpcpy(pathname, basedir);
  1950.                                         if (filename[0] == '\\') {
  1951.                                                 p = pathname;
  1952.                                                 if (*p && p[1] == ':') {
  1953.                                                         p += 2;
  1954.                                                 }
  1955.                                         }
  1956.                                         stpcpy(p, filename);
  1957.                                 } else {
  1958.                                         stpcpy(stpcpy(pathname, basedir), p);
  1959.                                 }
  1960.                         }
  1961.                         slash2yen(pathname);
  1962.                         strcpy(dospathname,pathname);
  1963.                         if (pathname[0] == 0)
  1964. #ifdef __TOS__
  1965.                         DosFile(dospathname);
  1966.                         UnixFile = strcmp(dospathname,pathname);
  1967.                         if (dospathname[strlen(dospathname)-1]=='\\')
  1968.                            goto weiter;
  1969. #endif
  1970.                         m=tstID(Hdr1.HeadID);
  1971.                         if (cmd != 'E' || tstdir(dospathname)) {
  1972.                                 if ((m = tstID(Hdr1.HeadID)) < 0) {
  1973.                                         printf("Skipped : '%s' : Unknown method\n", pathname);
  1974.                                 } else
  1975.                                 {
  1976.                                       cnt++;
  1977.                                       p = "Melting ";
  1978.                                       q = "Melted  ";
  1979.                                       switch (cmd) {
  1980.                                                   case 'X':
  1981.                                               case 'E':
  1982.  
  1983.                                                       if (flg_d == 0) printf("%s ", pathname);
  1984.                                                       file3 = fopen(outfname = dospathname, "wb");
  1985.                                                       break;
  1986.                                               case 'T':
  1987.                                                       if (flg_d == 0) printf("%s ", filename);
  1988. #ifndef __TOS__
  1989.                                                       file3 = fopen ("nul", "wb");
  1990. #else
  1991.                                                       file3 = NULL;   /* no NUL-Device supported! */
  1992. #endif
  1993.                                                       p = "Testing ";
  1994.                                                       q = "Tested  ";
  1995.                                                       break;
  1996.                                               case 'P':
  1997.                                                       if (flg_v != 2)
  1998.                                                               fprintf(file3, "<<< %s >>>\n", filename);
  1999.                                                       if (flg_v)
  2000.                                                               printf("%s ", filename);
  2001.                                                       fflush(file3);
  2002.  
  2003.  
  2004.                                                       setmode(fileno(file3), O_BINARY);
  2005.                                                       break;
  2006.                                         }
  2007. #ifndef __TOS__
  2008.                                         if ((ioctl(fileno(file3), 0) & 0x82) == 0x82) {
  2009.                                                 flg_n = 1;              /* Console output ? */
  2010.                                         } else {
  2011.                                                     setvbuf(file3, buf3, _IOFBF, BUFFERSIZ);
  2012.                                         }
  2013. #else
  2014.                                         if (file3 != NULL) {
  2015.                                                 if (file3 == stdout) {
  2016.                                                         flg_n = 1;              /* Console output ? */
  2017.                                                 } else {
  2018.                                                           outfile=file3;
  2019.                                                             /* MKoutputbuf(); */
  2020.                                                             /* setvbuf(file3, buf3, _IOFBF, BUFFERSIZ);   */
  2021.  
  2022.                                                 }
  2023.                                         } else OutBuf=NULL;
  2024. #endif
  2025.                                         if (m != 4)
  2026.                                            blkdisp(Hdr1.OrgSiz, p);
  2027.                                         else
  2028.                                            blkdisp(Hdr1.OrgSiz/2,p);
  2029.  
  2030.                                         outfile = file3;
  2031.                                         infile = file1;
  2032.  
  2033.  
  2034.                                         textsize = Hdr1.OrgSiz;
  2035.                                         codesize = Hdr1.PacSiz;
  2036.                                         crc = 0;
  2037.                                          if (m == 3) {
  2038.                                                  Decode();       /* extract LHarc's file */
  2039.                                          } else if (m == 1) {
  2040.                                                  DecodeOld();    /* extract LArc's file */
  2041.                                          } else if (m == 4)  {
  2042.                                                  decode_lh5(Hdr1.OrgSiz,Hdr1.PacSiz);
  2043.                                          } else {
  2044.                                                  crcflg = 1;
  2045.                                                  copyfile(infile, outfile, Hdr1.OrgSiz);
  2046.                                                  crcflg = 0;     /* only stored file */
  2047.                                          }
  2048.                                         fflush(file1);
  2049.                                         fseek(file1,ftell(file1),0);
  2050.                                         setvbuf(file1, buf2, _IOFBF, 1024);
  2051.                                         Mfree(TheInputBuf);
  2052.                                         if (file3 != NULL) {
  2053.                                                 Mfree(TheOutputBuf);
  2054.                                         }
  2055.                                         if (file3 != NULL && fflush(file3)) {
  2056.                                                 error(WTERR, outfname);
  2057.                                         }
  2058.                                         if (pathname[0] != 0)
  2059.                                         if (cmd == 'E') {
  2060.                                                 setftime(fileno(file3), &Hdr1.Ftime);
  2061.                                                 fclose(file3);
  2062.                                                 setfattr(pathname, Hdr1.Attr);
  2063.                                                 file3 = NULL;
  2064.                                         } else if (cmd == 'T') {
  2065. #ifndef __TOS__
  2066.                                                 fclose(file3);
  2067. #endif
  2068.                                         } else {
  2069.                                                 setmode(fileno(file3), O_TEXT);
  2070.                                                 if (flg_v != 2)
  2071.                                                         fprintf(file3, "\n");
  2072.                                         }
  2073.                                         curback();
  2074.                                         if (getcrc (&Hdr1) != crc) {
  2075.                                                 errorlevel = 1;                         /* test CRC */
  2076.                                                 printf("CRC err\n");
  2077.                                                 if (flg_m == 0) getchar();
  2078.                                         } else if (cmd != 'P' || flg_v != 0) {
  2079.                                                 if (flg_d == 0) printf("%s\n", q);
  2080.                                         }
  2081.                                 }
  2082.                         }
  2083.         weiter:
  2084.                         fseek(file1, arcpos0, SEEK_SET);        /* move pointer to next file */
  2085.                 } else {
  2086.                         fseek(file1, Hdr1.PacSiz, SEEK_CUR);
  2087.                 }
  2088.         }
  2089.         fclose(file1);
  2090.         file1 = NULL;
  2091.         return cnt;
  2092. }
  2093. /*}}}  */
  2094. /*{{{  delete:            d command*/
  2095.  
  2096. /*******************************
  2097.                 d command
  2098. *******************************/
  2099. void delete(void)
  2100. {
  2101.         int cnt = 0;
  2102.  
  2103.         openrwarc1();                                           /* open archive */
  2104.         if (patno == 0) {
  2105.                 error(NOFNERR, NULL);
  2106.         }
  2107.         message("Updating archive", arcname);
  2108.         openbackup1();                                          /* rename to temporary name */
  2109.         openbackup2();                                          /* open another temporary file */
  2110.         while (gethdr(file1, &Hdr1)) {
  2111.                 if (matchpat(filename)) {
  2112.                         message("Deleting", filename);
  2113.                         cnt++;
  2114.                         fseek(file1, Hdr1.PacSiz, SEEK_CUR);    /* skip file */
  2115.                 } else {
  2116.                         copyold();
  2117.                 }
  2118.         }
  2119.         endofupdate(cnt);                                       /* end-of-job process */
  2120. }
  2121. /*}}}  */
  2122. /*{{{  self:              s command*/
  2123.  
  2124. /*******************************
  2125.                 s command
  2126. *******************************/
  2127. void self(void)
  2128. {
  2129. #ifndef __TOS__
  2130.         uchar *p, /* *q,*/ buf[12], yn;
  2131.         int flg, i;
  2132.         long l, m, n;
  2133.         void sfx(void), sfx2(void);
  2134.  
  2135.         openarc1();                                                     /* open archive */
  2136.         message("Making Sfx from archive", arcname);
  2137.         stpcpy(stpcpy(backup2, workdir), "lharc.)2(");
  2138.         file2 = e_fopen(outfname = backup2, "w+b", MKTMPERR);
  2139.                                                                                         /* open temporary */
  2140.         while (gethdr(file1, &Hdr1)) {
  2141.                 flg = 0;
  2142.                 if (matchpat(filename)) {
  2143.                         if (flg_d == 0) printf("Extracting '%s' ", filename);
  2144.                         if (tstID(Hdr1.HeadID) < 2) {
  2145.                                 printf("(not supported) skipped.");
  2146.                         } else {
  2147.                                 if (flg_x == 0 && (p = strrchr(filename, '\\')) != NULL) {
  2148.                                          p++;                                    /* delete directory part */
  2149.                                         Hdr1.Fname[0] = strlen(p);
  2150.                                         i = p - filename;
  2151.                                         Hdr1.HeadSiz -= i;
  2152.                                         memcpy(Hdr1.Fname + 1, Hdr1.Fname + 1 + i,
  2153.                                                                                                 Hdr1.Fname[0] + 2);
  2154.                                         Hdr1.HeadChk = mksum(&Hdr1);    /* recalculate sum */
  2155.                                 }
  2156.                                 wthdr(&Hdr1);
  2157.                                 copyfile(file1, file2, Hdr1.PacSiz);
  2158.                                 flg = 1;
  2159.                         }
  2160.                         printf("\n");
  2161.                 }
  2162.                 if (flg == 0) {
  2163.                         fseek(file1, Hdr1.PacSiz, SEEK_CUR);
  2164.                 }
  2165.         }
  2166.         fclose(file1);
  2167.         if (putc(0, file2) == EOF)                      /* end-mark of archive */
  2168.                 error(WTERR, backup2);
  2169.         if ((l = ftell(file2)) <= 1) {
  2170.                 goto self9;
  2171.         }
  2172.         if (flg_x == 0) {
  2173.                 m = (uchar*)sfx2 - (uchar*)sfx;         /* size of sfx routine */
  2174.         } else {
  2175.                 m = (uchar*)usage - (uchar*)sfx2;
  2176.         }
  2177.         n = l + m;                                                              /* total size of sfx file */
  2178.         rewind(file2);
  2179.         infname = backup2;
  2180.         extfn(arcname, buf);                                    /* make the name of sfx */
  2181.         p = stpcpy(pathname, basedir);
  2182.         strcpy(&buf[8], "COM");
  2183.         if (flg_x || n > 0xfe80ul) {
  2184.                 strcpy(&buf[8], "EXE");
  2185.         }
  2186.         packfn(p, buf);
  2187.         if ((getfattr(pathname) & 0x8000) == 0) {       /* if the same name exists */
  2188.                 fprintf(stderr, "'%s' : %s", pathname, M_OVERWT);
  2189.                 yn = getyn();                                                   /* may overwrite */
  2190.                 if (yn == 'N') {
  2191.                         goto self9;
  2192.                 }
  2193.         }
  2194.         file3 = e_fopen(outfname = pathname, "wb", MKFILEERR);
  2195.         if (buf[8] == 'E') {                                            /* if .EXE */
  2196.                 if (flg_x) {
  2197.                         n = m;
  2198.                 }
  2199.                 n += 0x20;
  2200.                 ExeHdr.page = (n + 511) / 512;
  2201.                 ExeHdr.byte = n % 512;
  2202.                 ExeHdr.minalloc = (flg_x ? 0x66c0 : 0x2560) / 0x10;
  2203.                 if (fwrite(&ExeHdr, 0x20, 1, file3) == 0)
  2204.                         error(WTERR, pathname);
  2205.         }
  2206.         movedata(_CS, (flg_x ? (unsigned)sfx2 : (unsigned)sfx),
  2207.                          _DS, (unsigned)buf2, m);
  2208.         if (flg_x) {
  2209.                 memcpy(buf2 + 0x34, p, strlen(p));                              /* large ver. */
  2210.         } else {
  2211.                 *((uint *)buf2 + 1) = (l + m + 0x10f) / 0x10;   /* small ver. */
  2212.         }
  2213.         if (fwrite(buf2, m, 1, file3) == 0)     /* write sfx routine */
  2214.                 error(WTERR, pathname);
  2215.         if (flg_x) {
  2216.                 if (fwrite(keyword, strlen(keyword) + 1, 1, file3) == 0)
  2217.                         error(WTERR, pathname);
  2218.         }
  2219.         copyfile(file2, file3, l);                              /* write an archive */
  2220.         printf("\nCreated : '%s'\n", pathname);
  2221.         fclose(file3);
  2222. self9:
  2223.         fclose(file2);
  2224.         unlink(backup2);
  2225. #else
  2226.         fprintf (stderr, "Self-Extracting-Files: NOT YET IMPLEMENTED!!!\7\n");
  2227.         errorlevel = 1;
  2228.         longjmp (exit_jmp, 1);          /* NOT YET IMPLEMENTED !!! */
  2229. #endif
  2230. }
  2231. /*}}}  */
  2232. /*{{{  sysid*/
  2233.  
  2234. char *sysid( void )
  2235. {
  2236.   char *s;
  2237.   if (flg_k == 0) {
  2238.     switch(SystemId) {
  2239.       case 'M' : s="MSDOS "; break;
  2240.       case '2' : s="OS/2  "; break;
  2241.       case '9' : s="OS9   "; break;
  2242.       case 'K' : s="OS/68K"; break;
  2243.       case '3' : s="OS/386"; break;
  2244.       case 'H' : s="HUMAN "; break;
  2245.       case 'U' : s="UNIX  "; break;
  2246.       case 'C' : s="CP/M  "; break;
  2247.       case 'm' : s="Mac   "; break;
  2248.       case 'R' : s="Runser"; break;
  2249.       case 'A' : s="Atari "; break;
  2250.       default  : s="      "; break;
  2251.     }
  2252.   } else         s="      ";
  2253.   return s;
  2254. }
  2255.  
  2256. /*}}}  */
  2257. /*{{{  list:              l,v command*/
  2258.  
  2259.  
  2260. /*******************************
  2261.                 l, v command
  2262. *******************************/
  2263. void list(void)
  2264. {
  2265.         uint rt;
  2266.         uchar buf[79], *p,*b;
  2267.         static uchar attr[7] = "ohs--a";
  2268.         int i, j, k, Fno;
  2269.         ulong Osize, Psize;
  2270.  
  2271.         Osize = Psize = 0L;
  2272.         Fno = 0;
  2273.         openarc1();                                                                     /* open archive */
  2274.         UseExthdr=1;
  2275. #ifdef German
  2276.         printf("Inhalt von : '%s'\n\n", arcname);
  2277.         printf("  Name          Original   Gepackt   Rate"
  2278.                    "    Datum     Zeit Attr   Typ  CRC\n");
  2279. #else
  2280.         printf("Listing of archive : '%s'\n\n", arcname);
  2281.         printf("  Name          Original    Packed  Ratio"
  2282.                    "     Date   Time   Attr Type  CRC\n");
  2283. #endif
  2284.         printf("--------------  --------  -------- ------"
  2285.                    " -------- -------- ---- ----- ----\n");
  2286.         while ((p = gethdr(file1, &Hdr1)) != NULL) {
  2287.                 if (matchpat(filename)) {
  2288.                         rt = ratio(Hdr1.PacSiz, Hdr1.OrgSiz);
  2289.                         sprintf(buf, "              %10lu%10lu %3d.%1d%% "
  2290.                                         "%2d-%02d-%02d %2d:%02d:%02d ---w       %04X\n",
  2291.                                         Hdr1.OrgSiz, Hdr1.PacSiz, rt / 10, rt % 10,
  2292.                                         (Hdr1.Ftime.ft_year + 80) % 100, Hdr1.Ftime.ft_month,
  2293.                                         Hdr1.Ftime.ft_day, Hdr1.Ftime.ft_hour,
  2294.                                         Hdr1.Ftime.ft_min, Hdr1.Ftime.ft_tsec * 2,
  2295.                                         getcrc (&Hdr1));
  2296.                         memcpy(&buf[65], Hdr1.HeadID, 5);
  2297.                         for (i = 0, j = 1; i < 6; i++, j <<= 1) {       /* attributes */
  2298.                                 if (Hdr1.Attr & j) {
  2299.                                         k = attr[i];
  2300.                                         if (i <= 2) {
  2301.                                                 buf[63 - i] = k;
  2302.                                         } else {
  2303.                                                 buf[60] = k;
  2304.                                         }
  2305.                                 }
  2306.                         }
  2307.                         if (flg_x) {
  2308.                                 printf("%s\n", filename);       /* display in 2 lines */
  2309.                                 p=sysid(); b = buf;
  2310.                                 while (*p != 0) *b++=*p++;
  2311.  
  2312.                                 if (comment[0] != 0) printf("%s\n",comment);
  2313.                         } else {
  2314.                                 if (p != filename) {            /* display in one line */
  2315.                                         *buf = '+';
  2316.                                 }
  2317.                                 memcpy(&buf[2], p, strlen(p));
  2318.                         }
  2319.                         printf("%s", buf);
  2320.                         Fno ++;
  2321.                         Osize += Hdr1.OrgSiz;
  2322.                         Psize += Hdr1.PacSiz;
  2323.                 }
  2324.                 if (fseek(file1, Hdr1.PacSiz, 1))
  2325.                         break;
  2326.         }
  2327.         if (Fno) {
  2328.                 printf("--------------  --------  -------- ------"
  2329.                            " -------- --------\n");
  2330.                 rt = ratio(Psize, Osize);
  2331.                 getftime(fileno(file1), &arcstamp);
  2332.                 printf("   %3d files  %10lu%10lu %3d.%1d%% "
  2333.                            "%2d-%02d-%02d %2d:%02d:%02d\n",
  2334.                            Fno, Osize, Psize, rt / 10, rt % 10,
  2335.                            (arcstamp.ft_year + 80) % 100, arcstamp.ft_month,
  2336.                            arcstamp.ft_day, arcstamp.ft_hour,
  2337.                            arcstamp.ft_min, arcstamp.ft_tsec * 2);
  2338.         } else {
  2339.                 printf("    no file\n");
  2340.         }
  2341.         fclose(file1);
  2342. }
  2343. /*}}}  */
  2344. /*{{{  getsw:             get switches*/
  2345.  
  2346. /*******************************
  2347.                 get switches
  2348. *******************************/
  2349. void getsw(uchar *p)
  2350. {
  2351. #ifndef __TOS__
  2352.         static uchar flg[] = "rpxmacntvwyb";
  2353.         static uchar *flgpos[] = {&flg_r, &flg_p, &flg_x, &flg_m,
  2354.                                                           &flg_a, &flg_c, &flg_n, &flg_t,
  2355.                                                           &flg_v, &flg_w};
  2356. #else
  2357.         static uchar flg[] = "rpxmacntvwhybludoske5";
  2358.         static uchar *flgpos[] = {&flg_r, &flg_p, &flg_x, &flg_m,
  2359.                                                           &flg_a, &flg_c, &flg_n, &flg_t,
  2360.                                                           &flg_v, &flg_w, &flg_h};
  2361. #endif
  2362.         int i;
  2363.         uchar s;
  2364.         uchar *q;
  2365.  
  2366.         while ((s = *p++) != 0) {
  2367.                 q = strchr(flg, s);     /* search switch */
  2368.                 if (q) {
  2369.                         i = (int)(q - flg);
  2370.                         if (*p == '+') {
  2371.                                 *flgpos[i] = 1;
  2372.                                 p++;
  2373.                         } else if (*p == '-') {
  2374.                                 *flgpos[i] = 0;
  2375.                                 p++;
  2376.                         } else if (*p == '2') {
  2377.                                 *flgpos[i] = 2;
  2378.                                 p++;
  2379.                         } else if (s == 'v' && *p) {
  2380.                                 if (flg_v == 0)                 /* process of '/vSTRING' */
  2381.                                         flg_v = 1;
  2382.                                 pager = p;
  2383.                                 p = "";
  2384.                         } else if (s == 'y') flg_arc = 1;
  2385.                                                else if (s == 'k') { flg_k=1; elen=0; }
  2386.                         else if (s == 'b') {
  2387.                                 flg_arc=1;
  2388.                                 flg_backup=1;
  2389.                         } else if (s == '5') flg_5=1;
  2390.                           else if (s == 'l') FlgMethod=0;
  2391.                           else if (s == 'o') FlgMethod=1;
  2392.                           else if (s == 's') flg_s=1;
  2393.                           else if (s == 'u') flg_u = 1;
  2394.                           else if (s == 'e') flg_e = 1;
  2395.                           else if (s == 'w' && *p) {
  2396.                                 flg_w = 1;                              /* process of '/wSTRING' */
  2397.                                 wdir = p;
  2398.                                 p = "";
  2399.                         } else if (s == 'd') flg_n = flg_d = 1;
  2400.                         else {
  2401.                                 if (*flgpos[i]) {               /* flip-flop */
  2402.                                         *flgpos[i] = 0;
  2403.                                 } else {
  2404.                                         *flgpos[i] = 1;
  2405.                                 }
  2406.                         }
  2407.                         if (s == 'r' && flg_r > 0) {
  2408.                                 flg_x = 1;
  2409.                         }
  2410. #ifndef __TOS__
  2411.                 } else if (s == 'k') {
  2412.                         keyword = p;
  2413.                         p = "";
  2414. #endif
  2415.                 }
  2416.                 else {
  2417.                         if (s == '?') usage();
  2418.                         error(INVSWERR, NULL);
  2419.                 }
  2420.         }
  2421. }
  2422. /*}}}  */
  2423. /*{{{  executecmd:        execute command*/
  2424.  
  2425. /*******************************
  2426.                 execute command
  2427. *******************************/
  2428. void executecmd(void)
  2429. {
  2430.         int cnt;
  2431.  
  2432.         switch (cmd) {
  2433.         case 'A':
  2434.                 flg_c++;
  2435.         case 'U':
  2436.         case 'M':
  2437.                 append();
  2438.                 break;
  2439.         case 'C':
  2440.                 pack_afx();
  2441.                 break;
  2442.         case 'F':
  2443.                 freshen();
  2444.                 break;
  2445.         case 'P':
  2446.                 if (flg_v == 0) {
  2447.                    file3 = stdout;
  2448.                    goto common;
  2449.                 }
  2450.                 stpcpy(stpcpy(pathname, workdir), "LHARC.TMP"); /* view files */
  2451.                 file3 = e_fopen(outfname = pathname, "w", MKTMPERR);
  2452.                 cnt = extract();
  2453.                 fclose(file3);
  2454.                 if (cnt)                                                /* if any files extracted */
  2455. #ifndef __TOS__
  2456.                         stpcpy(stpcpy(stpcpy(buf2, pager), " "), pathname);
  2457.                         execute(buf2);                          /* execute by INT 0x2e */
  2458. #else
  2459.                         {
  2460.                                 int retcode;
  2461.  
  2462.                                 exec (pager, pathname, "", &retcode);
  2463.                         }
  2464. #endif
  2465. #if 0
  2466.                         spawnlp(P_WAIT, pager, pager, pathname, NULL);
  2467. #endif
  2468.                 unlink(pathname);
  2469.                 break;
  2470.         case 'T':
  2471.                 tstflg = 1;
  2472.                 goto common;
  2473.         case 'X':
  2474.         case 'E':
  2475.                 cmd = 'E';
  2476. common:
  2477.                 flg_v = 0;
  2478.                 extract();
  2479.                 break;
  2480.         case 'V':
  2481.                 flg_x++;
  2482.         case 'L':
  2483.                 list();
  2484.                 break;
  2485.         case 'D':
  2486.                 delete();
  2487.                 break;
  2488.         case 'S':
  2489.                 self();
  2490.                 break;
  2491.         }
  2492.         if (!flg_d) putchar('\n');
  2493. }
  2494. /*}}}  */
  2495. /*{{{  recoverbrk:        handle userbreak*/
  2496.  
  2497. /*******************************
  2498.                 handle userbreak
  2499. *******************************/
  2500. #ifndef __TOS__
  2501. int cbrk;
  2502.  
  2503. void recovercbrk(void) {
  2504.         setcbrk(cbrk);
  2505. }
  2506. #endif
  2507. /*}}}  */
  2508. /*{{{  OneNewFile:*/
  2509. void OneNewFile(char *p)
  2510. {
  2511.   char *s;
  2512.   s = strchr(p,'\n');
  2513.   if (s != NULL) *s='\0';
  2514.        if (patno == 0 && basedir == NULL &&
  2515.                 (strrchr(p, '\\') == p + strlen(p) - 1 ||
  2516.                  p[strlen(p) - 1] == ':')) {
  2517.                 basedir = p;    /* get base (or home) directory */
  2518.         } else if (patno >= MAX_PAT) {
  2519.                 message("File table overflow. ignore", p);
  2520.         } else {
  2521.                 patpath[patno] = p;
  2522.                 extfn(p, patfile[patno]);
  2523.                 patno++;                /* regist path names */
  2524.         }
  2525. }
  2526. /*}}}  */
  2527. /*{{{  newfile*/
  2528. void newfile(char *p)
  2529. {
  2530.   char file[128];       /* Dateiname bei &datei */
  2531.   FILE *f;
  2532.   if (*p == '&')
  2533.    {
  2534.      if (strcmp("-",&p[1]) == 0)
  2535.         f=stdin; else f=fopen(&p[1],"r");
  2536.      if (f != NULL)
  2537.      {
  2538.        while ( fgets(file,127,f) != NULL)
  2539.           OneNewFile(strdup(file));                     /* regist copy of filecontents */
  2540.        fclose(f);
  2541.      }
  2542.    } else OneNewFile(p);
  2543. }
  2544. /*}}}  */
  2545. /*{{{  argv_main:         main routine*/
  2546. /*******************************
  2547.                 main routine
  2548. *******************************/
  2549. #ifndef __GEM__
  2550. #ifdef __TOS__
  2551. int argvmain(int argc, uchar **argv,uchar **envp)
  2552. #else
  2553. int main(int argc, uchar *argv[])
  2554. #endif
  2555. {
  2556.         uchar *p, *q, *env, *env9;
  2557.         uchar ptitel=0;
  2558.         int yn;
  2559.         extern char title[];
  2560.         struct ffblk ffb;
  2561.         FILE *fp;
  2562.         char buffer[256];
  2563.  
  2564.  
  2565.  
  2566.         if (!setjmp (exit_jmp)) {
  2567. #ifndef __TOS__
  2568.                 ctrlbrk(userbreak);                     /* set vector for '^C' */
  2569.                 cbrk = getcbrk();
  2570.                 setcbrk(1);
  2571.                 atexit(recovercbrk);
  2572. #endif
  2573.  
  2574.                 remove("LHARC.)1(");
  2575.                 remove("LHARC.)2(");
  2576.  
  2577.                 mkcrc();                                                /* make CRC table */
  2578.                 swchar = getswchar();                   /* get the setting of switch char */
  2579.                 argc--;
  2580.                 argv++;
  2581.                 if (argc-- == 0)
  2582.                 {
  2583.                         flg_h = 1;
  2584.                         usage();                                        /* if no parameter given */
  2585.                 }
  2586.                 p = (argv++)[0];
  2587.                 cmd = toupper(*p);
  2588.                 if (strlen(p) - 1 || strchr("EXTDLVAUMFPSC", cmd) == 0) {
  2589.                         cmd = 'X';                                      /* if no command, assume 'X' command */
  2590.                         argc++;
  2591.                         argv--;
  2592.                         flg_x = 1;      /* @@25.5.91 Ohne Kommando x -rm */
  2593.                         flg_m = 1;
  2594.                 }
  2595.                 cmdupdate = (int)strchr("AUMFD", cmd);
  2596.                                                                                          /* command updating archive? */
  2597.                 if ((env = getenv("TMP")) != NULL) { /* get 'TMP' from environment */
  2598.                         wdir = env;
  2599.                         flg_w = 1;
  2600.                 }
  2601.                 if ((env = getenv("LHARC")) != NULL) {
  2602.                                                                         /* get 'LHARC' from environment */
  2603.                         for (p = env; *p != '\0'; p++) {
  2604.                                 if (*p == ' ' || *p == '\x08')
  2605.                                         *p = '\0';
  2606.                         }
  2607.                         env9 = p;
  2608.                         p = env;
  2609.                         while (p < env9) {
  2610.                                 while (*p == '\0') p++;
  2611.                                 if (*p == swchar || *p == '-') p++;
  2612.                                 getsw(p);
  2613.                                 while (*p) p++;
  2614.                         }
  2615.                 }
  2616.                 patno = -1;
  2617.                                 if (cmd == 'C') patno=0;
  2618.                 basedir = NULL;
  2619. while (argc--) {
  2620.         p = (argv++)[0];
  2621.         if (*p == swchar || *p == '-') {
  2622.                 getsw(++p);
  2623.         } else {
  2624.           if (ptitel == 0 && flg_d == 0) {
  2625.                 puts(title);                     /* output title */
  2626.                 if ((fp = fopen("lharc.ttp","rb")) != NULL ||
  2627.                     (fp = fopen("lzh.ttp","rb")) != NULL ||
  2628.                     (fp = fopen("lharcd.ttp","rb")) != NULL) {
  2629.                     fread(buffer,1,256,fp);
  2630.                      if (strncmp(buffer+30,"LArc's PFX",10) == 0)
  2631.                          printf(morefiles);
  2632.                   fclose(fp);
  2633.                 }
  2634.                 putchar('\n');
  2635.                 ptitel=1;
  2636.           }
  2637.                 strupr(p);
  2638.                 slash2yen(p);                           /* convert '/' to '\' */
  2639.                                                         /* in japanese version */
  2640.                 if (patno < 0) {                        /* get archive name */
  2641.                         strcpy(arcname, p);
  2642.                         if ((p = strrchr(arcname, '\\')) == NULL) {
  2643.                                 p = arcname;    /* pointer of the part of file name */
  2644.                         }
  2645.                         if ((q = strchr(p, '.')) == NULL) {
  2646.                                 strcat(arcname, ".LZH");        /* if no extension */
  2647.                         } else if (strcmp(".LZH", q) && flg_m == 0 && cmdupdate) {
  2648.                                 fprintf(stderr, M_NOTLZH, arcname);
  2649.                                 yn = getyn();   /* if the extension is not '.LZH' */
  2650.                                 if (yn == 'N') {
  2651.                                         errorlevel = 1;
  2652.                                         longjmp (exit_jmp, 1);
  2653.                                 }
  2654.                         }
  2655.                         patno++;
  2656.                 } else {
  2657.                                          newfile(p); /* Register file or files */
  2658.                 }
  2659.         }
  2660. }
  2661.                 if (patno < 0) {
  2662.                         error(NOARCNMERR, NULL);
  2663.                 }
  2664.                 if (patno == 0 && cmd != 'D') {                         /* if no name given */
  2665.                         extfn(patpath[0] = patnul, patfile[0]); /* '*.*' is assumed */
  2666.                         patno++;
  2667.                 }
  2668.                 p = stpcpy(workdir, wdir) - 1;
  2669.                 if (*workdir != '\0' && strrchr(workdir, '\\') != p && *p != ':') {
  2670.                         strcat(workdir, "\\");  /* concatenate '\' after the work dir. */
  2671.                 }
  2672.                 if (cmdupdate) {
  2673.                         if (strchr(arcname, '*') || strchr(arcname, '?')) {
  2674.                                 error(NOARCERR, arcname);
  2675.                         }                               /* when updating archive, wild cards can't used */
  2676.                         executecmd();
  2677.                 }
  2678.                 else {
  2679.                     if (cmd == 'C') executecmd();
  2680.                    else {
  2681.                       if (findfirst(arcname, &ffb, 0x07)) {
  2682.                               error(NOARCERR, arcname);
  2683.                       }
  2684.                       do {
  2685.                               strcpy(backpath(arcname), ffb.ff_name);
  2686.                               executecmd();
  2687.                       } while (!findnext(&ffb));
  2688.                       if (cmd != 'L' && cmd != 'V')
  2689.                               tstpat();                       /* whether all given names were used? */
  2690.                     }
  2691.                 }
  2692.         }
  2693.  
  2694. #ifdef __TOS__
  2695.         if (flg_h)
  2696.         {
  2697.                 fflush (stdin);                         /* wait for keystroke when used */
  2698.                 printf (M_PRESSKEY); /* with GEM-Desktop                         */
  2699.                 getch ();
  2700.                 putchar ('\n');
  2701.         }
  2702. #endif
  2703.         return errorlevel;
  2704. }
  2705. /*}}}  */
  2706. /*{{{  main:              argv calculations*/
  2707. int main (int argc, char *argv[], char *envp[])
  2708. {
  2709.   char **myargv;
  2710.   extern BASPAG *_BasPag;
  2711.   char *env;
  2712.   char *startpar;
  2713.   char *oldline;
  2714.  
  2715.  
  2716.   int count = 0;
  2717.   int i;
  2718.  
  2719.   Fsetdta (&_mydta);
  2720.  
  2721.   /* Anfang der alten Kommandozeile */
  2722.   oldline = &_BasPag->p_cmdlin[1];
  2723.  
  2724.   /* Flag fuer Verwendung von ARGV */
  2725.   if (_BasPag->p_cmdlin[0] != 127)
  2726.     return argvmain (argc, argv, envp);
  2727.  
  2728.   /* Zeiger auf Env-Var merken */
  2729.   env = getenv("ARGV");
  2730.   if (!env)
  2731.     return argvmain (argc, argv, envp);
  2732.  
  2733.   /* alle weiteren envp's loeschen */
  2734.   i = 0;
  2735.   while (strncmp (envp[i], "ARGV", 4)) i++;
  2736.   envp[i] = NULL;
  2737.  
  2738.   /* alles, was dahinter kommt, abschneiden */
  2739.   if (env[0] && env[-1])
  2740.   {
  2741.     *env++ = 0;     /* kill it */
  2742.     while (*env++);
  2743.   }
  2744.  
  2745.   /* Parameterstart */
  2746.   startpar = env;
  2747.  
  2748.   while (*env)
  2749.   {
  2750.     count++;
  2751.     while (*env++);
  2752.   }
  2753.  
  2754.   /* Speicher fuer neuen Argument-Vektor */
  2755.   myargv = Malloc ((count+1)*sizeof (char *));
  2756.   env = startpar;
  2757.  
  2758.   count = 0;
  2759.   while (*env)
  2760.   {
  2761.     myargv[count++] = env;
  2762.     while (*env++);
  2763.   }
  2764.   myargv[count] = NULL;
  2765.  
  2766.   /* moeglichst viele Parameter in alte Kommandozeile */
  2767.   {
  2768.     int i;
  2769.  
  2770.     *oldline = 0;
  2771.     i = 1;
  2772.  
  2773.     while ((i < count) && (strlen (oldline) + strlen (myargv[i]) < 120))
  2774.     {
  2775.       if (i > 1) strcat (oldline, " ");
  2776.       strcat (oldline, myargv[i]);
  2777.       i++;
  2778.     }
  2779.  
  2780.     if (i < count) strcat (oldline, " ...");
  2781.   }
  2782.  
  2783.  
  2784.   /* und ...argvmain() starten */
  2785.   count = argvmain (count, myargv, envp);
  2786.   Mfree (myargv);
  2787.   return count;
  2788. }
  2789. #endif
  2790. /*}}}  */
  2791.